@mentaproject/client 0.1.23 → 0.1.24

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.
@@ -1,7 +1,7 @@
1
1
  import { Address } from '@mentaproject/core/types';
2
2
  import { Account } from '../structures/Account';
3
- import { MentaClient, Transaction } from '../structures';
4
- import { GetTransactionsParams, IPersistenceAdapter } from 'src/types';
3
+ import { MentaClient } from '../structures';
4
+ import { GetTransactionsParams, IPersistenceAdapter, JSONTransaction } from 'src/types';
5
5
  /**
6
6
  * Manages the persistence of data, including transactions, using a specified persistence adapter.
7
7
  * It handles fetching data from both local storage and remote sources, and synchronizing them.
@@ -20,7 +20,7 @@ export declare class PersistenceManager {
20
20
  * @param params - Parameters for retrieving transactions.
21
21
  * @returns A promise that resolves to an array of transactions with associated account information.
22
22
  */
23
- getTransactions(address: Address, params: GetTransactionsParams): Promise<Transaction[]>;
23
+ getTransactions(address: Address, params: GetTransactionsParams): Promise<JSONTransaction<0>[]>;
24
24
  /**
25
25
  * Synchronizes an account's transactions from the remote source to the local persistence.
26
26
  * It fetches new transactions starting from the last synced block and updates the local storage.
@@ -40,7 +40,7 @@ export declare class TransactionManager {
40
40
  * @param {J} data - The JSON converted transaction data object.
41
41
  * @returns {Transaction} A Transaction instance representing the parsed transaction.
42
42
  */
43
- parse<J extends JSONTransaction<number>>(data: J): Transaction;
43
+ parse<J extends JSONTransaction<0>>(data: J): Transaction;
44
44
  /**
45
45
  * Sends a transaction to the blockchain network.
46
46
  * @description This method submits a new transaction to the blockchain. After the transaction
@@ -102,7 +102,8 @@ export class Account {
102
102
  const transactions = await Promise.all(hashes.map(hash => this.client.transactions.get({ hash })));
103
103
  return transactions;
104
104
  }
105
- return await this.persistenceManager.getTransactions(this.address, params);
105
+ const jsons = await this.persistenceManager.getTransactions(this.address, params);
106
+ return jsons.map(j => this.client.transactions.parse(j));
106
107
  }
107
108
  /**
108
109
  * Synchronizes the account's transactions with the remote data source using the configured `PersistenceManager`.
@@ -1,6 +1,7 @@
1
1
  import { Address } from '@mentaproject/core/types';
2
2
  import { Transaction } from '../structures/Transaction';
3
3
  import { GetTransactionsParams } from './Account';
4
+ import { JSONTransaction } from './Transaction';
4
5
  /**
5
6
  * @interface IPersistenceAdapter
6
7
  * @description Defines the contract for persistence layers, ensuring consistent data storage and retrieval operations.
@@ -17,9 +18,9 @@ export interface IPersistenceAdapter {
17
18
  * @method getTransactions
18
19
  * @description Retrieves a paginated list of transactions for a specific account based on provided filters.
19
20
  * @param {GetTransactionsFilters} filters - An object containing filters for retrieving transactions, such as account address, block range, pagination, and sort order.
20
- * @returns {Promise<Transaction[]>} A Promise that resolves with transactions objects.
21
+ * @returns {Promise<JSONTransaction[]>} A Promise that resolves with transactions objects.
21
22
  */
22
- getTransactions(address: Address, params: GetTransactionsParams): Promise<Transaction[]>;
23
+ getTransactions(address: Address, params: GetTransactionsParams): Promise<JSONTransaction<0>[]>;
23
24
  /**
24
25
  * @method getLastSyncedBlock
25
26
  * @description Retrieves the last synced block number for a given account. This is used to track the synchronization progress of an account's transactions.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mentaproject/client",
3
- "version": "0.1.23",
3
+ "version": "0.1.24",
4
4
  "description": "High level EVM library used into the Menta App to facilitate Blockchain interactions. ",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "scripts": {
24
24
  "test:file": "tsx test.ts",
25
- "test": "jest",
25
+ "test": "jest -i",
26
26
  "build": "tsc --project tsconfig.json",
27
27
  "patch": "npm version patch && npm run build && npm publish --access public",
28
28
  "minor": "npm version minor && npm run build && npm publish --access public",
package/src/index.ts ADDED
@@ -0,0 +1,21 @@
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
+ /**
9
+ * Re-exports all core data structures like MentaClient, Account, Block, and Transaction.
10
+ */
11
+ export * from './structures';
12
+ /**
13
+ * Re-exports all manager classes for interacting with different aspects of the Menta blockchain.
14
+ */
15
+ export * from './managers';
16
+ /**
17
+ * Re-exports the Cache structure for managing cached data.
18
+ */
19
+ export * from './structures/Cache';
20
+
21
+ export * from "./utils/bigint";
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @module AccountManager
3
+ */
4
+ import { Address } from "@mentaproject/core/types";
5
+ import { Account } from "../structures/Account";
6
+ import { PersistenceManager } from "./PersistenceManager";
7
+ import { MentaClient } from "../structures";
8
+
9
+ /**
10
+ * Manages blockchain account operations.
11
+ * This class provides methods to interact with accounts,
12
+ * including retrieving and managing them via an RPC client and a persistence manager.
13
+ *
14
+ * @class AccountManager
15
+ */
16
+ export class AccountManager {
17
+ /**
18
+ * Creates an instance of AccountManager.
19
+ *
20
+ * @param {MentaClient} client - The instance of MentaClient used to interact with the blockchain.
21
+ * @param {persistenceManager} persistenceManager - The optional persistence manager to store and retrieve account data.
22
+ */
23
+ constructor(public client: MentaClient, private persistenceManager?: PersistenceManager) { };
24
+
25
+ /**
26
+ * Retrieves an account instance by its blockchain address.
27
+ * @param address - The blockchain address of the account to retrieve.
28
+ * @returns An instance of the `Account` class.
29
+ * @example
30
+ * ```typescript
31
+ * import { MentaClient } from '@mentaproject/client';
32
+ * import { http } from '@mentaproject/core';
33
+ *
34
+ * // Initialize the MentaClient
35
+ * const client = new MentaClient({
36
+ * transport: http('http://rpcurlhere.com'),
37
+ * });
38
+ *
39
+ * // The address of the account to retrieve
40
+ * const accountAddress = '0x1234567890123456789012345678901234567890';
41
+ *
42
+ * // Retrieve the account instance using the account manager from the client
43
+ * const account = client.accounts.get(accountAddress);
44
+ *
45
+ * console.log(account.address); // 0x1234567890123456789012345678901234567890
46
+ * ```
47
+ */
48
+ get(address: Address): Account {
49
+ return new Account(this.client, { address: address }, this.persistenceManager);
50
+ };
51
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @module BlockManager
3
+ */
4
+ import { BlockTag, GetBlockParameters } from "@mentaproject/core/types";
5
+ import { Block } from "../structures/Block";
6
+ import { getBlock } from "@mentaproject/core/actions";
7
+ import { MentaClient } from "../structures";
8
+
9
+ /**
10
+ * Manages blockchain block-related operations, providing methods to interact with and retrieve block data.
11
+ */
12
+ export class BlockManager {
13
+ /**
14
+ * Creates an instance of BlockManager.
15
+ * @param client - The instance of MentaClient used to interact with the blockchain.
16
+ */
17
+ constructor(public client: MentaClient) {};
18
+
19
+ /**
20
+ * Retrieves a block from the blockchain based on the provided parameters.
21
+ * This method uses the underlying RPC client to fetch block data and then
22
+ * encapsulates it within a {@link Block} instance.
23
+ * @param params The parameters for retrieving the block, including block hash, block number, or block tag.
24
+ * @returns A promise that resolves to a {@link Block} instance representing the retrieved block.
25
+ * @example
26
+ * import { http } from '@mentaproject/core';
27
+ * import { mainnet } from '@mentaproject/core/chains';
28
+ * import { MentaClient } from '@mentaproject/client';
29
+ *
30
+ * // Initialize the MentaClient
31
+ * const mentaClient = new MentaClient({ chain: mainnet, transport: http("http://rpcurlhere.com") });
32
+ *
33
+ * async function fetchBlock() {
34
+ * // Retrieve the latest block
35
+ * const latestBlock = await mentaClient.blocks.get({ blockTag: 'latest' });
36
+ * console.log('Latest block number:', latestBlock.number);
37
+ *
38
+ * // Retrieve a specific block by its number
39
+ * if (latestBlock.number) {
40
+ * const specificBlock = await mentaClient.blocks.get({ blockNumber: latestBlock.number - 10n });
41
+ * console.log('Specific block hash:', specificBlock.hash);
42
+ * }
43
+ * }
44
+ *
45
+ * fetchBlock();
46
+ */
47
+ async get(params: GetBlockParameters<boolean, BlockTag>): Promise<Block> {
48
+ const data = await getBlock(this.client.rpc, params);
49
+ return new Block(this.client, data);
50
+ };
51
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @module ContractManager
3
+ */
4
+ import type { AbiItem } from "@mentaproject/core/types";
5
+ import { getContract, GetContractParameters } from "@mentaproject/contracts";
6
+ import { MentaClient } from "../structures";
7
+
8
+ /**
9
+ * Manages smart contract-related operations within the Menta client.
10
+ * This class provides methods to interact with smart contracts deployed on the blockchain,
11
+ * facilitating the retrieval of contract instances for various operations.
12
+ */
13
+ export class ContractManager {
14
+ /**
15
+ * Creates an instance of ContractManager.
16
+ * @description Initializes the ContractManager with a CoreClient instance, which is used for RPC communication.
17
+ * @param client - The instance of MentaClient used to interact with the blockchain.
18
+ */
19
+ constructor(protected client: MentaClient) {};
20
+
21
+ /**
22
+ * Retrieves a contract instance to interact with it.
23
+ * @description This method fetches a contract instance based on the provided parameters, allowing for interaction with its methods and events.
24
+ * @template P The type of the contract retrieval parameters, extending `GetContractParameters` with `AbiItem` array.
25
+ * @param {P} params The parameters for retrieving the contract, including its Application Binary Interface (ABI) and address.
26
+ * @returns {ReturnType<typeof getContract<ReadonlyArray<AbiItem>, P>>} A contract instance that can be used to call contract methods or listen to events.
27
+ * @example
28
+ * import { MentaClient } from '@mentaproject/client';
29
+ * import { http } from '@mentaproject/core';
30
+ *
31
+ * // Initialize the MentaClient with a transport
32
+ * const client = new MentaClient({
33
+ * transport: http('http://rpcurlhere.com'),
34
+ * });
35
+ *
36
+ * // Define the ABI and address for the smart contract
37
+ * const abi = [
38
+ * {
39
+ * "type": "function",
40
+ * "name": "greet",
41
+ * "stateMutability": "view",
42
+ * "inputs": [],
43
+ * "outputs": [{ "name": "", "type": "string" }]
44
+ * }
45
+ * ] as const;
46
+ * const contractAddress = '0x...'; // Replace with your contract address
47
+ *
48
+ * // Retrieve the contract instance
49
+ * const contract = client.contracts.get({
50
+ * abi,
51
+ * address: contractAddress,
52
+ * });
53
+ *
54
+ * // Example of interacting with the contract
55
+ * const greeting = await contract.greet();
56
+ */
57
+ get<P extends GetContractParameters<ReadonlyArray<AbiItem>>>(params: P) {
58
+ return getContract(this.client.rpc, params);
59
+ };
60
+ };
@@ -0,0 +1,59 @@
1
+ import { getBlockNumber } from '@mentaproject/core/actions';
2
+ import { Address } from '@mentaproject/core/types';
3
+
4
+ import { Account } from '../structures/Account';
5
+ import { MentaClient, Transaction } from '../structures';
6
+ import { bigIntMax } from '../utils/bigint';
7
+ import { GetTransactionsParams, IPersistenceAdapter, JSONTransaction } from 'src/types';
8
+
9
+ /**
10
+ * Manages the persistence of data, including transactions, using a specified persistence adapter.
11
+ * It handles fetching data from both local storage and remote sources, and synchronizing them.
12
+ */
13
+ export class PersistenceManager {
14
+ /**
15
+ * Creates an instance of PersistenceManager.
16
+ * @param client - The instance of MentaClient used to interact with the blockchain.
17
+ * @param persistenceAdapter - The adapter responsible for actual data persistence operations.
18
+ */
19
+ constructor(
20
+ private client: MentaClient,
21
+ private persistenceAdapter: IPersistenceAdapter
22
+ ) {}
23
+
24
+ /**
25
+ * Retrieves transactions for a given account, applying a "stale-while-revalidate" strategy.
26
+ * @param params - Parameters for retrieving transactions.
27
+ * @returns A promise that resolves to an array of transactions with associated account information.
28
+ */
29
+ public async getTransactions(address: Address, params: GetTransactionsParams): Promise<JSONTransaction<0>[]> {
30
+ return await this.persistenceAdapter.getTransactions(address, params);
31
+ }
32
+
33
+ /**
34
+ * Synchronizes an account's transactions from the remote source to the local persistence.
35
+ * It fetches new transactions starting from the last synced block and updates the local storage.
36
+ * @param account - The account whose transactions are to be synchronized.
37
+ * @param limit - The maximum number of transactions to fetch.
38
+ * @returns A promise that resolves when the synchronization is complete.
39
+ */
40
+ public async syncTransactions(account: Account, limit: number = 100_000): Promise<void> {
41
+ const lastSyncedBlock = await this.persistenceAdapter.getLastSyncedBlock(account.address);
42
+ const lastBlock = lastSyncedBlock ?? 0n;
43
+
44
+ const fromBlock = lastSyncedBlock ? lastSyncedBlock + 1n : (await getBlockNumber(this.client.rpc));
45
+
46
+ const newTransactions = await account.transactions({
47
+ fromBlock: fromBlock,
48
+ toBlock: lastBlock,
49
+ limit: limit
50
+ }, true)
51
+
52
+ if (newTransactions.length > 0) {
53
+ await this.persistenceAdapter.upsertTransactions(newTransactions);
54
+
55
+ const latestBlock = bigIntMax(...newTransactions.map(t => t.blockNumber || 0n));
56
+ await this.persistenceAdapter.setLastSyncedBlock(account.address, latestBlock);
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * @module TransactionManager
3
+ */
4
+ import { GetTransactionParameters, Transaction as RawTransaction, SendTransactionParameters } from "@mentaproject/core/types";
5
+ import { Transaction } from "../structures/Transaction";
6
+ import { getTransaction, sendTransaction } from "@mentaproject/core/actions";
7
+ import { MentaClient } from "../structures";
8
+ import { JSONTransaction } from "../types";
9
+ import { parseBingints } from "../utils/bigint";
10
+
11
+ /**
12
+ * Manages blockchain transaction-related operations, providing methods to retrieve and send transactions.
13
+ * @class
14
+ * @description This class provides an interface to interact with blockchain transactions,
15
+ * allowing for retrieval of transaction details and submission of new transactions
16
+ * to the network via an RPC client.
17
+ */
18
+ export class TransactionManager {
19
+ /**
20
+ * Creates an instance of `TransactionManager`.
21
+ * @constructor
22
+ * @param {MentaClient} client - The instance of MentaClient used to interact with the blockchain.
23
+ */
24
+ constructor(public client: MentaClient) {};
25
+
26
+ /**
27
+ * Retrieves a transaction by its hash or block number and index.
28
+ * @description This method fetches detailed information about a specific transaction
29
+ * from the blockchain using the provided parameters.
30
+ * @param {GetTransactionParameters} params - The parameters for retrieving the transaction,
31
+ * typically including `hash` or `blockNumber` and `index`.
32
+ * @returns {Promise<Transaction>} A promise that resolves to a {@link Transaction} instance
33
+ * containing the retrieved transaction data.
34
+ * @example
35
+ * const txHash = '0x...'; // Replace with a valid transaction hash
36
+ * const transaction = await client.transactions.get({ hash: txHash });
37
+ * console.log(transaction);
38
+ */
39
+ async get(params: GetTransactionParameters): Promise<Transaction> {
40
+ const data = await getTransaction(this.client.rpc, params);
41
+ return new Transaction(this.client, data);
42
+ };
43
+
44
+ /**
45
+ * Parse a transaction object from a JSON converted transaction data object.
46
+ *
47
+ * @param {J} data - The JSON converted transaction data object.
48
+ * @returns {Transaction} A Transaction instance representing the parsed transaction.
49
+ */
50
+ parse<J extends JSONTransaction<0>>(data: J): Transaction {
51
+ const parsed = parseBingints(data);
52
+
53
+ const rawData = {
54
+ ...parsed,
55
+ from: parsed.from.address,
56
+ to: parsed.to ? parsed.to.address : null,
57
+ };
58
+
59
+ return new Transaction(this.client, rawData as RawTransaction);
60
+ };
61
+
62
+ /**
63
+ * Sends a transaction to the blockchain network.
64
+ * @description This method submits a new transaction to the blockchain. After the transaction
65
+ * is successfully sent, it retrieves and returns the full transaction details.
66
+ * @param {SendTransactionParameters} params - The parameters required to send the transaction,
67
+ * such as `to`, `value`, `data`, `gasLimit`, etc.
68
+ * @returns {Promise<Transaction>} A promise that resolves to a {@link Transaction} instance
69
+ * representing the sent transaction, including its hash and other details.
70
+ * @example
71
+ * import { MentaClient } from '@mentaproject/client';
72
+ * import { http } from '@mentaproject/core';
73
+ *
74
+ * // This example assumes you have an account with funds, which is available to the client.
75
+ * const client = new MentaClient({
76
+ * chain: 'mainnet',
77
+ * transport: http('http://rpcurlhere.com')
78
+ * });
79
+ *
80
+ * const transactionResult = await client.transactions.send({
81
+ * to: '0xRecipientAddress...', // Replace with a valid recipient address
82
+ * value: 1000000000000000000n, // 1 ETH in wei
83
+ * });
84
+ *
85
+ * console.log('Transaction sent with hash:', transactionResult.hash);
86
+ */
87
+ async send(params: SendTransactionParameters): Promise<Transaction> {
88
+ const hash = await sendTransaction(this.client.rpc, params);
89
+
90
+ return await this.get({ hash });
91
+ };
92
+ };
@@ -0,0 +1,4 @@
1
+ export * from './AccountManager';
2
+ export * from './BlockManager';
3
+ export * from './ContractManager';
4
+ export * from './TransactionManager';
@@ -0,0 +1,206 @@
1
+ import { fetchByBlockRange, getBalance, getBlockNumber, getCode, getTransaction, getTransactionCount, sendTransaction, traceFilter } from "@mentaproject/core/actions";
2
+ import type { Address, Hash, onBlockRangeCallback } from "@mentaproject/core/types";
3
+ import { Transaction } from "./Transaction";
4
+ import { toHex } from "@mentaproject/core/utils";
5
+ import { AccountData, FetchTransactionParams, GetTransactionsParams, JSONAccount } from "../types/Account";
6
+ import { getContractType } from "@mentaproject/contracts";
7
+ import { toJSON } from "../utils/toJSON";
8
+ import { PersistenceManager } from "../managers/PersistenceManager";
9
+ import { MentaClient } from "./MentaClient";
10
+
11
+ /**
12
+ * Represents a blockchain account with functionalities to interact with the Menta blockchain.
13
+ * This class provides methods to query account information, send transactions, and manage account-related data.
14
+ */
15
+ export class Account implements AccountData {
16
+ /**
17
+ * The blockchain address of the account.
18
+ */
19
+ public address: Address;
20
+
21
+ private persistenceManager?: PersistenceManager;
22
+
23
+ /**
24
+ * Creates an instance of the Account class.
25
+ * @param client.rpc The CoreClient instance used for blockchain interactions.
26
+ * @param address The blockchain address of the account.
27
+ * @param persistenceManager An optional PersistenceManager instance for caching and data synchronization.
28
+ */
29
+ constructor(public client: MentaClient, data: AccountData, persistenceManager?: PersistenceManager) {
30
+ this.address = data.address;
31
+ this.persistenceManager = persistenceManager;
32
+ }
33
+
34
+ /**
35
+ * Checks if the account's address belongs to a smart contract.
36
+ * @description This method queries the blockchain for the code associated with the account's address.
37
+ * If code is found, it indicates that the account is a contract.
38
+ * @returns {Promise<boolean>} A promise that resolves to `true` if the account is a contract, `false` otherwise.
39
+ */
40
+ async isContract(): Promise<boolean> {
41
+ const code = await getCode(this.client.rpc, { address: this.address });
42
+
43
+ if (!code || code === "0x") return false;
44
+ return true;
45
+ };
46
+
47
+ /**
48
+ * Retrieves the type of the contract if the account is a smart contract.
49
+ * @description This method first checks if the account is a contract using `isContract()`.
50
+ * If it is a contract, it then attempts to determine and return its type.
51
+ * @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.
52
+ */
53
+ async contractType(): Promise<any> {
54
+ const isContract = await this.isContract();
55
+ if (!isContract) return undefined;
56
+
57
+ return await getContractType(this.client.rpc, this.address);
58
+ };
59
+
60
+ /**
61
+ * Sends a specified amount of native cryptocurrency (ETH) to this account.
62
+ * @description This method constructs and sends a transaction to transfer ETH to the account's address.
63
+ * @param {bigint} amount The amount of ETH to send, specified in wei (the smallest denomination of Ether).
64
+ * @returns {Promise<Transaction>} A promise that resolves to a `Transaction` object representing the sent transaction.
65
+ */
66
+ async sendETH(amount: bigint): Promise<Transaction> {
67
+ const hash = await sendTransaction(this.client.rpc, {
68
+ calls: [{
69
+ to: this.address,
70
+ value: amount,
71
+ }]
72
+ });
73
+
74
+ const data = await getTransaction(this.client.rpc, { hash });
75
+ return new Transaction(this.client, data);
76
+ };
77
+
78
+ /**
79
+ * Retrieves the current native cryptocurrency (ETH) balance of the account.
80
+ * @description This method queries the blockchain to get the balance associated with the account's address.
81
+ * @returns {Promise<bigint>} A promise that resolves to the ETH balance of the account, in wei.
82
+ */
83
+ async ETHBalance(): Promise<bigint> {
84
+ return await getBalance(this.client.rpc, {
85
+ address: this.address,
86
+ });
87
+ };
88
+
89
+ /**
90
+ * Retrieves the transaction count (nonce) for the account.
91
+ * @description The transaction count represents the number of transactions sent from this account,
92
+ * which is also used as the nonce for new transactions to prevent replay attacks.
93
+ * @returns {Promise<number>} A promise that resolves to the transaction count of the account.
94
+ */
95
+ async transactionCount(): Promise<number> {
96
+ return await getTransactionCount(this.client.rpc, { address: this.address });
97
+ }
98
+
99
+ /**
100
+ * Retrieves all transactions involving this account.
101
+ * @description If a `PersistenceManager` is configured, this method will first attempt to retrieve transactions from the local cache.
102
+ * If not found in cache or if no `PersistenceManager` is configured, it will fetch transactions directly from the remote RPC.
103
+ * @param {GetTransactionsOptions} [options] - Optional parameters for filtering, pagination, and sorting the transactions.
104
+ * @param {number} [options.startBlock] - The starting block number (inclusive) from which to retrieve transactions.
105
+ * @param {number} [options.endBlock] - The ending block number (inclusive) up to which to retrieve transactions.
106
+ * @param {number} [options.page] - The page number for paginated results.
107
+ * @param {number} [options.offset] - The number of items to skip from the beginning of the result set.
108
+ * @param {'asc' | 'desc'} [options.sort] - The sorting order for transactions based on block number ('asc' for ascending, 'desc' for descending).
109
+ * @param {boolean} [forceFetch=false] - Forces the method to fetch transactions from the remote source even if they are already cached. (mostly used internally)
110
+ * @returns {Promise<Transaction[]>} A promise that resolves to an array of transactions.
111
+ */
112
+ async transactions(params: GetTransactionsParams, forceFetch = false): Promise<Transaction[]> {
113
+ if (!this.persistenceManager || forceFetch) {
114
+ // If persistence is not configured, fetch directly from remote
115
+ const hashes = await this._fetchTransactions(params);
116
+ const transactions = await Promise.all(hashes.map(hash => this.client.transactions.get({ hash })));
117
+
118
+ return transactions;
119
+ }
120
+
121
+ const jsons = await this.persistenceManager.getTransactions(this.address, params);
122
+ return jsons.map(j => this.client.transactions.parse(j));
123
+ }
124
+
125
+ /**
126
+ * Synchronizes the account's transactions with the remote data source using the configured `PersistenceManager`.
127
+ * @description This method initiates a synchronization process to ensure that the local cache of transactions
128
+ * for this account is up-to-date with the blockchain.
129
+ * @param {number} [limit] The maximum number of transactions to synchronize.
130
+ * @returns {Promise<void>} A promise that resolves when the synchronization process is complete.
131
+ * @throws {Error} If the persistence module is not configured.
132
+ */
133
+ async syncTransactions(limit: number = 1000): Promise<void> {
134
+ if (!this.persistenceManager) throw new Error("The persistence module is not configured.");
135
+ await this.persistenceManager.syncTransactions(this, limit);
136
+ }
137
+
138
+ /**
139
+ * Retrieves transactions involving a specific token. (not implemented yet)
140
+ * @description This method queries the persistence adapter to retrieve transactions involving a specific token.
141
+ * @param {Address} tokenAddress The address of the token.
142
+ * @returns {Promise<any>} A promise that resolves to an array of transactions involving the token.
143
+ * @throws {Error} If the persistence module is not configured.
144
+ */
145
+ async tokenTransactions(tokenAddress: Address): Promise<any> {
146
+ if (!this.persistenceManager) throw new Error('The persistence module is not configured.');
147
+
148
+ return {};
149
+ }
150
+
151
+ /**
152
+ * Converts the Account instance into a JSON-serializable representation.
153
+ * @description This method leverages a utility function to convert the `Account` object,
154
+ * including its asynchronous properties (like `isContract`, `ETHBalance`), into a plain JSON object.
155
+ * @param {number} [depth=1] The depth to which nested objects should be converted. A depth of 1 means only direct properties are included.
156
+ * @returns {Promise<object>} A promise that resolves to the JSON representation of the account.
157
+ */
158
+ async toJSON<D extends number = 1>(depth: D): Promise<JSONAccount<D>> {
159
+ return await toJSON({
160
+ obj: {
161
+ address: this.address,
162
+ isContract: this.isContract.bind(this),
163
+ contractType: this.contractType.bind(this),
164
+ ETHBalance: this.ETHBalance.bind(this),
165
+ transactionCount: this.transactionCount.bind(this),
166
+ },
167
+ depth
168
+ });
169
+ }
170
+
171
+ /**
172
+ * Fetches transactions from the account using a block range exploration with trace_filter calls.
173
+ *
174
+ * @param params - The parameters for the block range exploration.
175
+ * @returns A Promise that resolves to an array of transaction hashes.
176
+ */
177
+ protected async _fetchTransactions({ fromBlock, toBlock, limit = 50 }: FetchTransactionParams): Promise<Hash[]> {
178
+ const lastBlock = await getBlockNumber(this.client.rpc);
179
+
180
+ const onBlockRange: onBlockRangeCallback = async ({ fromBlock, toBlock }, stop) => {
181
+ const outgoing = await traceFilter(this.client.rpc, {
182
+ fromBlock: toHex(fromBlock),
183
+ toBlock: toHex(toBlock),
184
+ fromAddress: this.address
185
+ });
186
+
187
+ const incoming = await traceFilter(this.client.rpc, {
188
+ fromBlock: toHex(fromBlock),
189
+ toBlock: toHex(toBlock),
190
+ toAddress: this.address
191
+ });
192
+
193
+ const traces = outgoing.concat(incoming).sort((a, b) => a.blockNumber - b.blockNumber);
194
+
195
+ return traces.map(t => t.transactionHash as Hash)
196
+ };
197
+
198
+ return await fetchByBlockRange({
199
+ toBlock: BigInt(toBlock !== undefined ? toBlock : 0),
200
+ fromBlock: BigInt(fromBlock !== undefined ? fromBlock : lastBlock),
201
+ direction: "backward",
202
+ itemLimit: limit,
203
+ onBlockRange
204
+ });
205
+ }
206
+ };