@mentaproject/client 0.1.23 → 0.1.25
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/managers/PersistenceManager.d.ts +3 -3
- package/dist/managers/TransactionManager.d.ts +1 -1
- package/dist/structures/Account.d.ts +1 -1
- package/dist/structures/Account.js +21 -19
- package/dist/structures/MentaClient.d.ts +5 -2
- package/dist/structures/MentaClient.js +24 -5
- package/dist/types/MentaClient.d.ts +10 -2
- package/dist/types/MentaClient.js +0 -2
- package/dist/types/PersistenceAdapter.d.ts +3 -2
- package/package.json +4 -4
- package/src/index.ts +21 -0
- package/src/managers/AccountManager.ts +51 -0
- package/src/managers/BlockManager.ts +51 -0
- package/src/managers/ContractManager.ts +60 -0
- package/src/managers/PersistenceManager.ts +59 -0
- package/src/managers/TransactionManager.ts +92 -0
- package/src/managers/index.ts +4 -0
- package/src/structures/Account.ts +251 -0
- package/src/structures/Block.ts +185 -0
- package/src/structures/Cache.ts +126 -0
- package/src/structures/MentaClient.ts +152 -0
- package/src/structures/Transaction.ts +220 -0
- package/src/structures/index.ts +5 -0
- package/src/types/Account.ts +44 -0
- package/src/types/Block.ts +14 -0
- package/src/types/Cache.ts +55 -0
- package/src/types/JsonRPC.ts +126 -0
- package/src/types/MentaClient.ts +79 -0
- package/src/types/PersistenceAdapter.ts +44 -0
- package/src/types/Transaction.ts +52 -0
- package/src/types/Utils.ts +30 -0
- package/src/types/index.ts +8 -0
- package/src/utils/bigint.ts +59 -0
- package/src/utils/toJSON.ts +123 -0
- package/src/utils/withCache.ts +50 -0
- package/test.ts +0 -89
- package/transactions.json +0 -1302
|
@@ -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,251 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fetchByBlockRange,
|
|
3
|
+
getBalance,
|
|
4
|
+
getBlockNumber,
|
|
5
|
+
getCode,
|
|
6
|
+
getTransaction,
|
|
7
|
+
getTransactionCount,
|
|
8
|
+
sendTransaction,
|
|
9
|
+
traceFilter,
|
|
10
|
+
} from "@mentaproject/core/actions";
|
|
11
|
+
import type {
|
|
12
|
+
Address,
|
|
13
|
+
Hash,
|
|
14
|
+
onBlockRangeCallback,
|
|
15
|
+
} from "@mentaproject/core/types";
|
|
16
|
+
import { Transaction } from "./Transaction";
|
|
17
|
+
import { toHex } from "@mentaproject/core/utils";
|
|
18
|
+
import {
|
|
19
|
+
AccountData,
|
|
20
|
+
FetchTransactionParams,
|
|
21
|
+
GetTransactionsParams,
|
|
22
|
+
JSONAccount,
|
|
23
|
+
} from "../types/Account";
|
|
24
|
+
import { getContractType } from "@mentaproject/contracts";
|
|
25
|
+
import { toJSON } from "../utils/toJSON";
|
|
26
|
+
import { PersistenceManager } from "../managers/PersistenceManager";
|
|
27
|
+
import { MentaClient } from "./MentaClient";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Represents a blockchain account with functionalities to interact with the Menta blockchain.
|
|
31
|
+
* This class provides methods to query account information, send transactions, and manage account-related data.
|
|
32
|
+
*/
|
|
33
|
+
export class Account implements AccountData {
|
|
34
|
+
/**
|
|
35
|
+
* The blockchain address of the account.
|
|
36
|
+
*/
|
|
37
|
+
public address: Address;
|
|
38
|
+
|
|
39
|
+
private persistenceManager?: PersistenceManager;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Creates an instance of the Account class.
|
|
43
|
+
* @param client.rpc The CoreClient instance used for blockchain interactions.
|
|
44
|
+
* @param address The blockchain address of the account.
|
|
45
|
+
* @param persistenceManager An optional PersistenceManager instance for caching and data synchronization.
|
|
46
|
+
*/
|
|
47
|
+
constructor(
|
|
48
|
+
public client: MentaClient,
|
|
49
|
+
data: AccountData,
|
|
50
|
+
persistenceManager?: PersistenceManager,
|
|
51
|
+
) {
|
|
52
|
+
this.address = data.address;
|
|
53
|
+
this.persistenceManager = persistenceManager;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Checks if the account's address belongs to a smart contract.
|
|
58
|
+
* @description This method queries the blockchain for the code associated with the account's address.
|
|
59
|
+
* If code is found, it indicates that the account is a contract.
|
|
60
|
+
* @returns {Promise<boolean>} A promise that resolves to `true` if the account is a contract, `false` otherwise.
|
|
61
|
+
*/
|
|
62
|
+
async isContract(): Promise<boolean> {
|
|
63
|
+
const code = await getCode(this.client.rpc, { address: this.address });
|
|
64
|
+
|
|
65
|
+
if (!code || code === "0x") return false;
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Retrieves the type of the contract if the account is a smart contract.
|
|
71
|
+
* @description This method first checks if the account is a contract using `isContract()`.
|
|
72
|
+
* If it is a contract, it then attempts to determine and return its type.
|
|
73
|
+
* @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.
|
|
74
|
+
*/
|
|
75
|
+
async contractType(): Promise<any> {
|
|
76
|
+
const isContract = await this.isContract();
|
|
77
|
+
if (!isContract) return undefined;
|
|
78
|
+
|
|
79
|
+
return await getContractType(this.client.rpc, this.address);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Sends a specified amount of native cryptocurrency (ETH) to this account.
|
|
84
|
+
* @description This method constructs and sends a transaction to transfer ETH to the account's address.
|
|
85
|
+
* @param {bigint} amount The amount of ETH to send, specified in wei (the smallest denomination of Ether).
|
|
86
|
+
* @returns {Promise<Transaction>} A promise that resolves to a `Transaction` object representing the sent transaction.
|
|
87
|
+
*/
|
|
88
|
+
async sendETH(amount: bigint): Promise<Transaction> {
|
|
89
|
+
const hash = await sendTransaction(this.client.rpc, {
|
|
90
|
+
calls: [
|
|
91
|
+
{
|
|
92
|
+
to: this.address,
|
|
93
|
+
value: amount,
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const data = await getTransaction(this.client.rpc, { hash });
|
|
99
|
+
return new Transaction(this.client, data);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Retrieves the current native cryptocurrency (ETH) balance of the account.
|
|
104
|
+
* @description This method queries the blockchain to get the balance associated with the account's address.
|
|
105
|
+
* @returns {Promise<bigint>} A promise that resolves to the ETH balance of the account, in wei.
|
|
106
|
+
*/
|
|
107
|
+
async ETHBalance(): Promise<bigint> {
|
|
108
|
+
return await getBalance(this.client.rpc, {
|
|
109
|
+
address: this.address,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Retrieves the transaction count (nonce) for the account.
|
|
115
|
+
* @description The transaction count represents the number of transactions sent from this account,
|
|
116
|
+
* which is also used as the nonce for new transactions to prevent replay attacks.
|
|
117
|
+
* @returns {Promise<number>} A promise that resolves to the transaction count of the account.
|
|
118
|
+
*/
|
|
119
|
+
async transactionCount(): Promise<number> {
|
|
120
|
+
return await getTransactionCount(this.client.rpc, {
|
|
121
|
+
address: this.address,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Retrieves all transactions involving this account.
|
|
127
|
+
* @description If a `PersistenceManager` is configured, this method will first attempt to retrieve transactions from the local cache.
|
|
128
|
+
* If not found in cache or if no `PersistenceManager` is configured, it will fetch transactions directly from the remote RPC.
|
|
129
|
+
* @param {GetTransactionsOptions} [options] - Optional parameters for filtering, pagination, and sorting the transactions.
|
|
130
|
+
* @param {number} [options.startBlock] - The starting block number (inclusive) from which to retrieve transactions.
|
|
131
|
+
* @param {number} [options.endBlock] - The ending block number (inclusive) up to which to retrieve transactions.
|
|
132
|
+
* @param {number} [options.page] - The page number for paginated results.
|
|
133
|
+
* @param {number} [options.offset] - The number of items to skip from the beginning of the result set.
|
|
134
|
+
* @param {'asc' | 'desc'} [options.sort] - The sorting order for transactions based on block number ('asc' for ascending, 'desc' for descending).
|
|
135
|
+
* @param {boolean} [forceFetch=false] - Forces the method to fetch transactions from the remote source even if they are already cached. (mostly used internally)
|
|
136
|
+
* @returns {Promise<Transaction[]>} A promise that resolves to an array of transactions.
|
|
137
|
+
*/
|
|
138
|
+
async transactions(
|
|
139
|
+
params: GetTransactionsParams,
|
|
140
|
+
forceFetch = false,
|
|
141
|
+
): Promise<Transaction[]> {
|
|
142
|
+
if (!this.persistenceManager || forceFetch) {
|
|
143
|
+
// If persistence is not configured, fetch directly from remote
|
|
144
|
+
const hashes = await this._fetchTransactions(params);
|
|
145
|
+
const transactions = await Promise.all(
|
|
146
|
+
hashes.map((hash) => this.client.transactions.get({ hash })),
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
return transactions;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const jsons = await this.persistenceManager.getTransactions(
|
|
153
|
+
this.address,
|
|
154
|
+
params,
|
|
155
|
+
);
|
|
156
|
+
return jsons.map((j) => this.client.transactions.parse(j));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Synchronizes the account's transactions with the remote data source using the configured `PersistenceManager`.
|
|
161
|
+
* @description This method initiates a synchronization process to ensure that the local cache of transactions
|
|
162
|
+
* for this account is up-to-date with the blockchain.
|
|
163
|
+
* @param {number} [limit] The maximum number of transactions to synchronize.
|
|
164
|
+
* @returns {Promise<void>} A promise that resolves when the synchronization process is complete.
|
|
165
|
+
* @throws {Error} If the persistence module is not configured.
|
|
166
|
+
*/
|
|
167
|
+
async syncTransactions(limit: number = 1000): Promise<void> {
|
|
168
|
+
if (!this.persistenceManager)
|
|
169
|
+
throw new Error("The persistence module is not configured.");
|
|
170
|
+
await this.persistenceManager.syncTransactions(this, limit);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Retrieves transactions involving a specific token. (not implemented yet)
|
|
175
|
+
* @description This method queries the persistence adapter to retrieve transactions involving a specific token.
|
|
176
|
+
* @param {Address} tokenAddress The address of the token.
|
|
177
|
+
* @returns {Promise<any>} A promise that resolves to an array of transactions involving the token.
|
|
178
|
+
* @throws {Error} If the persistence module is not configured.
|
|
179
|
+
*/
|
|
180
|
+
async tokenTransactions(tokenAddress: Address): Promise<any> {
|
|
181
|
+
if (!this.persistenceManager)
|
|
182
|
+
throw new Error("The persistence module is not configured.");
|
|
183
|
+
|
|
184
|
+
return {};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Converts the Account instance into a JSON-serializable representation.
|
|
189
|
+
* @description This method leverages a utility function to convert the `Account` object,
|
|
190
|
+
* including its asynchronous properties (like `isContract`, `ETHBalance`), into a plain JSON object.
|
|
191
|
+
* @param {number} [depth=1] The depth to which nested objects should be converted. A depth of 1 means only direct properties are included.
|
|
192
|
+
* @returns {Promise<object>} A promise that resolves to the JSON representation of the account.
|
|
193
|
+
*/
|
|
194
|
+
async toJSON<D extends number = 1>(depth: D): Promise<JSONAccount<D>> {
|
|
195
|
+
return await toJSON({
|
|
196
|
+
obj: {
|
|
197
|
+
address: this.address,
|
|
198
|
+
isContract: this.isContract.bind(this),
|
|
199
|
+
contractType: this.contractType.bind(this),
|
|
200
|
+
ETHBalance: this.ETHBalance.bind(this),
|
|
201
|
+
transactionCount: this.transactionCount.bind(this),
|
|
202
|
+
},
|
|
203
|
+
depth,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Fetches transactions from the account using a block range exploration with trace_filter calls.
|
|
209
|
+
*
|
|
210
|
+
* @param params - The parameters for the block range exploration.
|
|
211
|
+
* @returns A Promise that resolves to an array of transaction hashes.
|
|
212
|
+
*/
|
|
213
|
+
protected async _fetchTransactions({
|
|
214
|
+
fromBlock,
|
|
215
|
+
toBlock,
|
|
216
|
+
limit = 50,
|
|
217
|
+
}: FetchTransactionParams): Promise<Hash[]> {
|
|
218
|
+
const lastBlock = await getBlockNumber(this.client.rpc);
|
|
219
|
+
|
|
220
|
+
const onBlockRange: onBlockRangeCallback = async (
|
|
221
|
+
{ fromBlock, toBlock },
|
|
222
|
+
stop,
|
|
223
|
+
) => {
|
|
224
|
+
const outgoing = await traceFilter(this.client.rpc, {
|
|
225
|
+
fromBlock: toHex(fromBlock),
|
|
226
|
+
toBlock: toHex(toBlock),
|
|
227
|
+
fromAddress: this.address,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const incoming = await traceFilter(this.client.rpc, {
|
|
231
|
+
fromBlock: toHex(fromBlock),
|
|
232
|
+
toBlock: toHex(toBlock),
|
|
233
|
+
toAddress: this.address,
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
const traces = outgoing
|
|
237
|
+
.concat(incoming)
|
|
238
|
+
.sort((a, b) => a.blockNumber - b.blockNumber);
|
|
239
|
+
|
|
240
|
+
return traces.map((t) => t.transactionHash as Hash);
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
return await fetchByBlockRange({
|
|
244
|
+
toBlock: BigInt(toBlock !== undefined ? toBlock : 0),
|
|
245
|
+
fromBlock: BigInt(fromBlock !== undefined ? fromBlock : lastBlock),
|
|
246
|
+
direction: "backward",
|
|
247
|
+
itemLimit: limit,
|
|
248
|
+
onBlockRange,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { Block as RawBlock, Hash, Hex, Withdrawal } from "@mentaproject/core";
|
|
2
|
+
|
|
3
|
+
import { Account } from "./Account";
|
|
4
|
+
import { Transaction } from "./Transaction";
|
|
5
|
+
import { JSONBlock } from "../types/Block";
|
|
6
|
+
import { toJSON } from "../utils/toJSON";
|
|
7
|
+
import { MentaClient } from "./MentaClient";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @description Represents a blockchain block with its properties and methods.
|
|
11
|
+
* This class provides a structured way to access block-related data and interact with the blockchain client.
|
|
12
|
+
*/
|
|
13
|
+
export class Block implements Omit<RawBlock, "miner" | "transactions"> {
|
|
14
|
+
/**
|
|
15
|
+
* @description The base fee per gas for the block.
|
|
16
|
+
*/
|
|
17
|
+
baseFeePerGas: bigint | null
|
|
18
|
+
/**
|
|
19
|
+
* @description The gas used for blobs in the block.
|
|
20
|
+
*/
|
|
21
|
+
blobGasUsed: bigint
|
|
22
|
+
/**
|
|
23
|
+
* @description The block's difficulty.
|
|
24
|
+
*/
|
|
25
|
+
difficulty: bigint
|
|
26
|
+
/**
|
|
27
|
+
* @description The excess blob gas in the block.
|
|
28
|
+
*/
|
|
29
|
+
excessBlobGas: bigint
|
|
30
|
+
/**
|
|
31
|
+
* @description Extra data included in the block.
|
|
32
|
+
*/
|
|
33
|
+
extraData: Hex
|
|
34
|
+
/**
|
|
35
|
+
* @description The gas limit for the block.
|
|
36
|
+
*/
|
|
37
|
+
gasLimit: bigint
|
|
38
|
+
/**
|
|
39
|
+
* @description The gas used in the block.
|
|
40
|
+
*/
|
|
41
|
+
gasUsed: bigint
|
|
42
|
+
/**
|
|
43
|
+
* @description The hash of the block.
|
|
44
|
+
*/
|
|
45
|
+
hash: Hash | null
|
|
46
|
+
/**
|
|
47
|
+
* @description The logs bloom filter for the block.
|
|
48
|
+
*/
|
|
49
|
+
logsBloom: Hex | null
|
|
50
|
+
/**
|
|
51
|
+
* @description The mix hash of the block.
|
|
52
|
+
*/
|
|
53
|
+
mixHash: Hash
|
|
54
|
+
/**
|
|
55
|
+
* @description The nonce of the block.
|
|
56
|
+
*/
|
|
57
|
+
nonce: Hex | null
|
|
58
|
+
/**
|
|
59
|
+
* @description The block number.
|
|
60
|
+
*/
|
|
61
|
+
number: bigint | null
|
|
62
|
+
/**
|
|
63
|
+
* @description The parent beacon block root.
|
|
64
|
+
*/
|
|
65
|
+
parentBeaconBlockRoot?: Hex
|
|
66
|
+
/**
|
|
67
|
+
* @description The hash of the parent block.
|
|
68
|
+
*/
|
|
69
|
+
parentHash: Hash
|
|
70
|
+
/**
|
|
71
|
+
* @description The root of the receipts trie.
|
|
72
|
+
*/
|
|
73
|
+
receiptsRoot: Hex
|
|
74
|
+
/**
|
|
75
|
+
* @description The seal fields of the block.
|
|
76
|
+
*/
|
|
77
|
+
sealFields: Hex[]
|
|
78
|
+
/**
|
|
79
|
+
* @description The SHA3 uncles hash.
|
|
80
|
+
*/
|
|
81
|
+
sha3Uncles: Hash
|
|
82
|
+
/**
|
|
83
|
+
* @description The size of the block in bytes.
|
|
84
|
+
*/
|
|
85
|
+
size: bigint
|
|
86
|
+
/**
|
|
87
|
+
* @description The state root of the block.
|
|
88
|
+
*/
|
|
89
|
+
stateRoot: Hash
|
|
90
|
+
/**
|
|
91
|
+
* @description The timestamp of the block.
|
|
92
|
+
*/
|
|
93
|
+
timestamp: bigint
|
|
94
|
+
/**
|
|
95
|
+
* @description The total difficulty of the chain up to this block.
|
|
96
|
+
*/
|
|
97
|
+
totalDifficulty: bigint | null
|
|
98
|
+
/**
|
|
99
|
+
* @description The root of the transactions trie.
|
|
100
|
+
*/
|
|
101
|
+
transactionsRoot: Hash
|
|
102
|
+
/**
|
|
103
|
+
* @description The list of uncle hashes.
|
|
104
|
+
*/
|
|
105
|
+
uncles: Hash[]
|
|
106
|
+
/**
|
|
107
|
+
* @description The list of withdrawals.
|
|
108
|
+
*/
|
|
109
|
+
withdrawals?: Withdrawal[]
|
|
110
|
+
/**
|
|
111
|
+
* @description The root of the withdrawals trie.
|
|
112
|
+
*/
|
|
113
|
+
withdrawalsRoot?: Hex
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @description The miner of the block, represented as an Account instance.
|
|
117
|
+
*/
|
|
118
|
+
miner: Account
|
|
119
|
+
/**
|
|
120
|
+
* @description The transactions included in the block, represented as an array of Transaction instances.
|
|
121
|
+
*/
|
|
122
|
+
transactions?: Transaction[] | Hash[]
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @description Creates an instance of Block.
|
|
126
|
+
* @param client - The instance of MentaClient used to interact with the blockchain.
|
|
127
|
+
* @param data The raw block data conforming to IBlockData.
|
|
128
|
+
* @param includeTransactions Whether to include full transaction objects. Defaults to false.
|
|
129
|
+
*/
|
|
130
|
+
constructor(public client: MentaClient, data: RawBlock) {
|
|
131
|
+
this.baseFeePerGas = data.baseFeePerGas;
|
|
132
|
+
this.blobGasUsed = data.blobGasUsed;
|
|
133
|
+
this.difficulty = data.difficulty;
|
|
134
|
+
this.excessBlobGas = data.excessBlobGas;
|
|
135
|
+
this.extraData = data.extraData;
|
|
136
|
+
this.gasLimit = data.gasLimit;
|
|
137
|
+
this.gasUsed = data.gasUsed;
|
|
138
|
+
this.hash = data.hash;
|
|
139
|
+
this.logsBloom = data.logsBloom;
|
|
140
|
+
this.mixHash = data.mixHash;
|
|
141
|
+
this.nonce = data.nonce;
|
|
142
|
+
this.number = data.number;
|
|
143
|
+
this.parentBeaconBlockRoot = data.parentBeaconBlockRoot;
|
|
144
|
+
this.parentHash = data.parentHash;
|
|
145
|
+
this.receiptsRoot = data.receiptsRoot;
|
|
146
|
+
this.sealFields = data.sealFields;
|
|
147
|
+
this.sha3Uncles = data.sha3Uncles;
|
|
148
|
+
this.size = data.size;
|
|
149
|
+
this.stateRoot = data.stateRoot;
|
|
150
|
+
this.timestamp = data.timestamp;
|
|
151
|
+
this.totalDifficulty = data.totalDifficulty;
|
|
152
|
+
this.transactionsRoot = data.transactionsRoot;
|
|
153
|
+
this.uncles = data.uncles;
|
|
154
|
+
this.withdrawals = data.withdrawals;
|
|
155
|
+
this.withdrawalsRoot = data.withdrawalsRoot;
|
|
156
|
+
|
|
157
|
+
this.miner = new Account(this.client, { address: data.miner});
|
|
158
|
+
|
|
159
|
+
if (!data.transactions || data.transactions.length === 0) {
|
|
160
|
+
const parsed = data.transactions.map((data) => typeof data === "string" ? data : new Transaction(this.client, data))
|
|
161
|
+
this.transactions = parsed as Transaction[] | Hash[];
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
protected includeTransactions(): this is this & { transactions: Transaction[] } {
|
|
166
|
+
if (!this.transactions || this.transactions.length === 0) return false;
|
|
167
|
+
return true
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* @description Converts the Block instance to a JSON representation.
|
|
172
|
+
* This method serializes the block's properties into a plain JavaScript object,
|
|
173
|
+
* suitable for JSON serialization.
|
|
174
|
+
* @param depth The depth of the conversion. Defaults to 1.
|
|
175
|
+
* @returns A promise that resolves to the JSON representation of the block.
|
|
176
|
+
*/
|
|
177
|
+
async toJSON<D extends number = 1>(depth: D): Promise<JSONBlock<D>> {
|
|
178
|
+
return await toJSON({
|
|
179
|
+
obj: {
|
|
180
|
+
...this,
|
|
181
|
+
},
|
|
182
|
+
depth
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module MemoryCache
|
|
3
|
+
*/
|
|
4
|
+
import { ICache, ICacheEntry, ICacheConfig } from '../types/Cache';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
/**
|
|
8
|
+
* @class MemoryCache
|
|
9
|
+
* @description A simple in-memory cache implementation that adheres to the ICache interface.
|
|
10
|
+
* It stores key-value pairs with an associated time-to-live (TTL) based on block numbers.
|
|
11
|
+
* The cache automatically evicts the oldest entries when its maximum size is reached.
|
|
12
|
+
*/
|
|
13
|
+
export class MemoryCache implements ICache {
|
|
14
|
+
/**
|
|
15
|
+
* @property {Map<string, ICacheEntry<any>>} cache - The internal Map used to store cache entries.
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
private cache = new Map<string, ICacheEntry<any>>();
|
|
19
|
+
/**
|
|
20
|
+
* @property {ICacheConfig} config - The configuration object for the cache, including maxSize, defaultTtl, and ttlPolicies.
|
|
21
|
+
*/
|
|
22
|
+
public config: ICacheConfig;
|
|
23
|
+
/**
|
|
24
|
+
* @property {bigint} blockNumber - The current block number used for TTL calculations.
|
|
25
|
+
* @private
|
|
26
|
+
*/
|
|
27
|
+
private blockNumber: bigint;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @constructor
|
|
31
|
+
* @description Creates an instance of MemoryCache.
|
|
32
|
+
* @param {bigint} blockNumber - The current block number to use for TTL calculations.
|
|
33
|
+
* @param {Partial<ICacheConfig>} [options] - Optional configuration for the cache.
|
|
34
|
+
* @param {number} [options.maxSize=500] - The maximum number of entries the cache can hold.
|
|
35
|
+
* @param {number} [options.defaultTtl=1] - The default time-to-live in blocks for cache entries if not specified.
|
|
36
|
+
* @param {Object.<string, number>} [options.ttlPolicies={}] - A map of specific TTL policies for different keys.
|
|
37
|
+
*/
|
|
38
|
+
constructor(blockNumber: bigint, options?: Partial<ICacheConfig>) {
|
|
39
|
+
this.blockNumber = blockNumber;
|
|
40
|
+
this.config = {
|
|
41
|
+
maxSize: 500,
|
|
42
|
+
defaultTtl: 1,
|
|
43
|
+
ttlPolicies: options?.ttlPolicies || {},
|
|
44
|
+
...options,
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @method isExpired
|
|
50
|
+
* @description Checks if a cache entry has expired based on the current block number and the entry's expiry block.
|
|
51
|
+
* @param {bigint} expiry - The expiry block number of the cache entry.
|
|
52
|
+
* @returns {boolean} `true` if the entry has expired, `false` otherwise.
|
|
53
|
+
* @protected
|
|
54
|
+
*/
|
|
55
|
+
protected isExpired(expiry: bigint): boolean {
|
|
56
|
+
return this.blockNumber > expiry;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @method setBlockNumber
|
|
61
|
+
* @description Sets the current block number for TTL calculations. This is crucial for managing cache entry expiry.
|
|
62
|
+
* @param {bigint} blockNumber - The new current block number.
|
|
63
|
+
* @returns {void}
|
|
64
|
+
*/
|
|
65
|
+
setBlockNumber(blockNumber: bigint): void {
|
|
66
|
+
this.blockNumber = blockNumber;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @method set
|
|
71
|
+
* @description Sets a value in the cache. If the key already exists, its entry will be updated.
|
|
72
|
+
* If the cache reaches its maximum size, the oldest entry will be evicted before adding the new one.
|
|
73
|
+
* @template T - The type of the value being stored.
|
|
74
|
+
* @param {string} key - The unique key for the cache entry.
|
|
75
|
+
* @param {T} value - The value to store in the cache.
|
|
76
|
+
* @param {number} [ttl=this.config.defaultTtl] - The time-to-live (in blocks) for this specific entry. Defaults to the cache's `defaultTtl`.
|
|
77
|
+
* @returns {void}
|
|
78
|
+
*/
|
|
79
|
+
set<T>(key: string, value: T, ttl: number = this.config.defaultTtl): void {
|
|
80
|
+
if (this.cache.has(key)) {
|
|
81
|
+
this.cache.delete(key);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (this.cache.size >= this.config.maxSize) this.evict();
|
|
85
|
+
|
|
86
|
+
const expiry = this.blockNumber + BigInt(ttl);
|
|
87
|
+
this.cache.set(key, { value, expiry });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @method get
|
|
92
|
+
* @description Retrieves a value from the cache. If the entry is found and has not expired,
|
|
93
|
+
* it is moved to the end of the cache (making it the most recently used) to prevent premature eviction.
|
|
94
|
+
* @template T - The expected type of the value.
|
|
95
|
+
* @param {string} key - The key of the cache entry to retrieve.
|
|
96
|
+
* @returns {T | undefined} The cached value if found and not expired, otherwise `undefined`.
|
|
97
|
+
*/
|
|
98
|
+
get<T>(key: string): T | undefined {
|
|
99
|
+
const entry = this.cache.get(key);
|
|
100
|
+
if (!entry) return undefined;
|
|
101
|
+
|
|
102
|
+
if (this.isExpired(entry.expiry)) {
|
|
103
|
+
this.cache.delete(key);
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
this.cache.delete(key);
|
|
108
|
+
this.cache.set(key, entry);
|
|
109
|
+
|
|
110
|
+
return entry.value as T;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @method evict
|
|
115
|
+
* @description Evicts the oldest entry from the cache. This method is called internally when the cache
|
|
116
|
+
* reaches its `maxSize` to make room for new entries.
|
|
117
|
+
* @returns {void}
|
|
118
|
+
* @private
|
|
119
|
+
*/
|
|
120
|
+
private evict(): void {
|
|
121
|
+
const oldestKey = this.cache.keys().next().value;
|
|
122
|
+
if (!oldestKey) return;
|
|
123
|
+
|
|
124
|
+
this.cache.delete(oldestKey);
|
|
125
|
+
}
|
|
126
|
+
}
|