@hashgraphonline/standards-sdk 0.0.111 → 0.0.112-canary.0
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/cjs/hcs-10/base-client.d.ts +46 -1
- package/dist/cjs/hcs-10/base-client.d.ts.map +1 -1
- package/dist/cjs/hcs-10/browser.d.ts +30 -0
- package/dist/cjs/hcs-10/browser.d.ts.map +1 -1
- package/dist/cjs/hcs-10/sdk.d.ts.map +1 -1
- package/dist/cjs/hcs-10/types.d.ts +34 -0
- package/dist/cjs/hcs-10/types.d.ts.map +1 -1
- package/dist/cjs/index-BmPzMkW9.cjs +11 -0
- package/dist/cjs/index-BmPzMkW9.cjs.map +1 -0
- package/dist/cjs/{index-CHar8dVv-B3h_fMlF.cjs → index-CHar8dVv-CUVf-if8.cjs} +2 -2
- package/dist/cjs/{index-CHar8dVv-B3h_fMlF.cjs.map → index-CHar8dVv-CUVf-if8.cjs.map} +1 -1
- package/dist/cjs/services/mirror-node.d.ts +230 -2
- package/dist/cjs/services/mirror-node.d.ts.map +1 -1
- package/dist/cjs/services/types.d.ts +328 -0
- package/dist/cjs/services/types.d.ts.map +1 -1
- package/dist/cjs/standards-sdk.cjs +1 -1
- package/dist/es/hcs-10/base-client.d.ts +46 -1
- package/dist/es/hcs-10/base-client.d.ts.map +1 -1
- package/dist/es/hcs-10/browser.d.ts +30 -0
- package/dist/es/hcs-10/browser.d.ts.map +1 -1
- package/dist/es/hcs-10/sdk.d.ts.map +1 -1
- package/dist/es/hcs-10/types.d.ts +34 -0
- package/dist/es/hcs-10/types.d.ts.map +1 -1
- package/dist/es/services/mirror-node.d.ts +230 -2
- package/dist/es/services/mirror-node.d.ts.map +1 -1
- package/dist/es/services/types.d.ts +328 -0
- package/dist/es/services/types.d.ts.map +1 -1
- package/dist/es/standards-sdk.es19.js +6 -6
- package/dist/es/standards-sdk.es20.js +1 -1
- package/dist/es/standards-sdk.es21.js +658 -10
- package/dist/es/standards-sdk.es21.js.map +1 -1
- package/dist/es/standards-sdk.es24.js +7139 -450
- package/dist/es/standards-sdk.es24.js.map +1 -1
- package/dist/es/standards-sdk.es25.js +2 -109
- package/dist/es/standards-sdk.es25.js.map +1 -1
- package/dist/es/standards-sdk.es26.js +469 -34
- package/dist/es/standards-sdk.es26.js.map +1 -1
- package/dist/es/standards-sdk.es27.js +74 -222
- package/dist/es/standards-sdk.es27.js.map +1 -1
- package/dist/es/standards-sdk.es28.js +34 -141
- package/dist/es/standards-sdk.es28.js.map +1 -1
- package/dist/es/standards-sdk.es29.js +251 -5
- package/dist/es/standards-sdk.es29.js.map +1 -1
- package/dist/es/standards-sdk.es30.js +154 -7171
- package/dist/es/standards-sdk.es30.js.map +1 -1
- package/dist/es/standards-sdk.es31.js +11 -2
- package/dist/es/standards-sdk.es31.js.map +1 -1
- package/dist/es/standards-sdk.es32.js +7135 -41
- package/dist/es/standards-sdk.es32.js.map +1 -1
- package/dist/es/standards-sdk.es33.js +41 -7135
- package/dist/es/standards-sdk.es33.js.map +1 -1
- package/dist/es/standards-sdk.es5.js +10 -1
- package/dist/es/standards-sdk.es5.js.map +1 -1
- package/dist/es/standards-sdk.es7.js +3 -2
- package/dist/es/standards-sdk.es7.js.map +1 -1
- package/dist/es/standards-sdk.es8.js +3 -2
- package/dist/es/standards-sdk.es8.js.map +1 -1
- package/dist/es/standards-sdk.es9.js +1 -1
- package/dist/umd/hcs-10/base-client.d.ts +46 -1
- package/dist/umd/hcs-10/base-client.d.ts.map +1 -1
- package/dist/umd/hcs-10/browser.d.ts +30 -0
- package/dist/umd/hcs-10/browser.d.ts.map +1 -1
- package/dist/umd/hcs-10/sdk.d.ts.map +1 -1
- package/dist/umd/hcs-10/types.d.ts +34 -0
- package/dist/umd/hcs-10/types.d.ts.map +1 -1
- package/dist/umd/services/mirror-node.d.ts +230 -2
- package/dist/umd/services/mirror-node.d.ts.map +1 -1
- package/dist/umd/services/types.d.ts +328 -0
- package/dist/umd/services/types.d.ts.map +1 -1
- package/dist/umd/standards-sdk.umd.js +12 -12
- package/dist/umd/standards-sdk.umd.js.map +1 -1
- package/package.json +1 -1
- package/dist/cjs/index-B0xnKxrq.cjs +0 -11
- package/dist/cjs/index-B0xnKxrq.cjs.map +0 -1
|
@@ -4,18 +4,26 @@ import axios from "axios";
|
|
|
4
4
|
import { Logger } from "./standards-sdk.es15.js";
|
|
5
5
|
import { proto } from "@hashgraph/proto";
|
|
6
6
|
class HederaMirrorNode {
|
|
7
|
-
constructor(network, logger) {
|
|
7
|
+
constructor(network, logger, config) {
|
|
8
8
|
this.maxRetries = 3;
|
|
9
9
|
this.initialDelayMs = 1e3;
|
|
10
10
|
this.maxDelayMs = 3e4;
|
|
11
11
|
this.backoffFactor = 2;
|
|
12
12
|
this.network = network;
|
|
13
|
-
this.
|
|
13
|
+
this.apiKey = config?.apiKey;
|
|
14
|
+
this.customHeaders = config?.headers || {};
|
|
15
|
+
this.baseUrl = config?.customUrl || this.getMirrorNodeUrl();
|
|
14
16
|
this.logger = logger || new Logger({
|
|
15
17
|
level: "debug",
|
|
16
18
|
module: "MirrorNode"
|
|
17
19
|
});
|
|
18
20
|
this.isServerEnvironment = typeof window === "undefined";
|
|
21
|
+
if (config?.customUrl) {
|
|
22
|
+
this.logger.info(`Using custom mirror node URL: ${config.customUrl}`);
|
|
23
|
+
}
|
|
24
|
+
if (config?.apiKey) {
|
|
25
|
+
this.logger.info("Using API key for mirror node requests");
|
|
26
|
+
}
|
|
19
27
|
}
|
|
20
28
|
/**
|
|
21
29
|
* Configures the retry mechanism for API requests.
|
|
@@ -30,6 +38,36 @@ class HederaMirrorNode {
|
|
|
30
38
|
`Retry configuration updated: maxRetries=${this.maxRetries}, initialDelayMs=${this.initialDelayMs}, maxDelayMs=${this.maxDelayMs}, backoffFactor=${this.backoffFactor}`
|
|
31
39
|
);
|
|
32
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Updates the mirror node configuration.
|
|
43
|
+
* @param config The new mirror node configuration.
|
|
44
|
+
*/
|
|
45
|
+
configureMirrorNode(config) {
|
|
46
|
+
if (config.customUrl) {
|
|
47
|
+
this.baseUrl = config.customUrl;
|
|
48
|
+
this.logger.info(`Updated mirror node URL: ${config.customUrl}`);
|
|
49
|
+
}
|
|
50
|
+
if (config.apiKey) {
|
|
51
|
+
this.apiKey = config.apiKey;
|
|
52
|
+
this.logger.info("Updated API key for mirror node requests");
|
|
53
|
+
}
|
|
54
|
+
if (config.headers) {
|
|
55
|
+
this.customHeaders = { ...this.customHeaders, ...config.headers };
|
|
56
|
+
this.logger.info("Updated custom headers for mirror node requests");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Constructs a full URL for API requests, handling custom providers with API keys in the path.
|
|
61
|
+
* @param endpoint The API endpoint (e.g., '/api/v1/accounts/0.0.123')
|
|
62
|
+
* @returns The full URL for the request
|
|
63
|
+
*/
|
|
64
|
+
constructUrl(endpoint) {
|
|
65
|
+
if (this.baseUrl.includes("<API-KEY>") && this.apiKey) {
|
|
66
|
+
const baseUrlWithKey = this.baseUrl.replace("<API-KEY>", this.apiKey);
|
|
67
|
+
return endpoint.startsWith("/") ? `${baseUrlWithKey}${endpoint}` : `${baseUrlWithKey}/${endpoint}`;
|
|
68
|
+
}
|
|
69
|
+
return endpoint.startsWith("/") ? `${this.baseUrl}${endpoint}` : `${this.baseUrl}/${endpoint}`;
|
|
70
|
+
}
|
|
33
71
|
getMirrorNodeUrl() {
|
|
34
72
|
return this.network === "mainnet" ? "https://mainnet-public.mirrornode.hedera.com" : "https://testnet.mirrornode.hedera.com";
|
|
35
73
|
}
|
|
@@ -67,7 +105,7 @@ class HederaMirrorNode {
|
|
|
67
105
|
*/
|
|
68
106
|
async getAccountMemo(accountId) {
|
|
69
107
|
this.logger.info(`Getting account memo for account ID: ${accountId}`);
|
|
70
|
-
const accountInfoUrl =
|
|
108
|
+
const accountInfoUrl = this.constructUrl(`/api/v1/accounts/${accountId}`);
|
|
71
109
|
try {
|
|
72
110
|
const accountInfo = await this._requestWithRetry(
|
|
73
111
|
accountInfoUrl
|
|
@@ -93,7 +131,7 @@ class HederaMirrorNode {
|
|
|
93
131
|
*/
|
|
94
132
|
async getTopicInfo(topicId) {
|
|
95
133
|
try {
|
|
96
|
-
const topicInfoUrl =
|
|
134
|
+
const topicInfoUrl = this.constructUrl(`/api/v1/topics/${topicId}`);
|
|
97
135
|
this.logger.debug(`Fetching topic info from ${topicInfoUrl}`);
|
|
98
136
|
const data = await this._requestWithRetry(topicInfoUrl);
|
|
99
137
|
return data;
|
|
@@ -151,7 +189,7 @@ class HederaMirrorNode {
|
|
|
151
189
|
async getTokenInfo(tokenId) {
|
|
152
190
|
this.logger.debug(`Fetching token info for ${tokenId}`);
|
|
153
191
|
try {
|
|
154
|
-
const tokenInfoUrl =
|
|
192
|
+
const tokenInfoUrl = this.constructUrl(`/api/v1/tokens/${tokenId}`);
|
|
155
193
|
const data = await this._requestWithRetry(
|
|
156
194
|
tokenInfoUrl
|
|
157
195
|
);
|
|
@@ -176,7 +214,7 @@ class HederaMirrorNode {
|
|
|
176
214
|
*/
|
|
177
215
|
async getTopicMessages(topicId) {
|
|
178
216
|
this.logger.trace(`Querying messages for topic ${topicId}`);
|
|
179
|
-
let nextUrl =
|
|
217
|
+
let nextUrl = this.constructUrl(`/api/v1/topics/${topicId}/messages`);
|
|
180
218
|
const messages = [];
|
|
181
219
|
while (nextUrl) {
|
|
182
220
|
try {
|
|
@@ -230,7 +268,7 @@ class HederaMirrorNode {
|
|
|
230
268
|
}
|
|
231
269
|
}
|
|
232
270
|
}
|
|
233
|
-
nextUrl = data.links?.next ?
|
|
271
|
+
nextUrl = data.links?.next ? this.constructUrl(data.links.next) : "";
|
|
234
272
|
} catch (e) {
|
|
235
273
|
const error = e;
|
|
236
274
|
const logMessage = `Error querying topic messages for topic ${topicId} (URL: ${nextUrl}) after retries: ${error.message}`;
|
|
@@ -248,7 +286,7 @@ class HederaMirrorNode {
|
|
|
248
286
|
*/
|
|
249
287
|
async requestAccount(accountId) {
|
|
250
288
|
try {
|
|
251
|
-
const accountInfoUrl =
|
|
289
|
+
const accountInfoUrl = this.constructUrl(`/api/v1/accounts/${accountId}`);
|
|
252
290
|
this.logger.debug(`Requesting account info from ${accountInfoUrl}`);
|
|
253
291
|
const data = await this._requestWithRetry(
|
|
254
292
|
accountInfoUrl
|
|
@@ -445,9 +483,23 @@ class HederaMirrorNode {
|
|
|
445
483
|
async _requestWithRetry(url, axiosConfig) {
|
|
446
484
|
let attempt = 0;
|
|
447
485
|
let delay = this.initialDelayMs;
|
|
486
|
+
const config = {
|
|
487
|
+
...axiosConfig,
|
|
488
|
+
headers: {
|
|
489
|
+
...this.customHeaders,
|
|
490
|
+
...axiosConfig?.headers
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
if (this.apiKey) {
|
|
494
|
+
config.headers = {
|
|
495
|
+
...config.headers,
|
|
496
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
497
|
+
"X-API-Key": this.apiKey
|
|
498
|
+
};
|
|
499
|
+
}
|
|
448
500
|
while (attempt < this.maxRetries) {
|
|
449
501
|
try {
|
|
450
|
-
const response = await axios.get(url,
|
|
502
|
+
const response = await axios.get(url, config);
|
|
451
503
|
return response.data;
|
|
452
504
|
} catch (error) {
|
|
453
505
|
attempt++;
|
|
@@ -482,9 +534,33 @@ class HederaMirrorNode {
|
|
|
482
534
|
async _fetchWithRetry(url, fetchOptions) {
|
|
483
535
|
let attempt = 0;
|
|
484
536
|
let delay = this.initialDelayMs;
|
|
537
|
+
const headers = {
|
|
538
|
+
...this.customHeaders
|
|
539
|
+
};
|
|
540
|
+
if (fetchOptions?.headers) {
|
|
541
|
+
if (fetchOptions.headers instanceof Headers) {
|
|
542
|
+
fetchOptions.headers.forEach((value, key) => {
|
|
543
|
+
headers[key] = value;
|
|
544
|
+
});
|
|
545
|
+
} else if (Array.isArray(fetchOptions.headers)) {
|
|
546
|
+
fetchOptions.headers.forEach(([key, value]) => {
|
|
547
|
+
headers[key] = value;
|
|
548
|
+
});
|
|
549
|
+
} else {
|
|
550
|
+
Object.assign(headers, fetchOptions.headers);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
if (this.apiKey) {
|
|
554
|
+
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
555
|
+
headers["X-API-Key"] = this.apiKey;
|
|
556
|
+
}
|
|
557
|
+
const options = {
|
|
558
|
+
...fetchOptions,
|
|
559
|
+
headers
|
|
560
|
+
};
|
|
485
561
|
while (attempt < this.maxRetries) {
|
|
486
562
|
try {
|
|
487
|
-
const request = await fetch(url,
|
|
563
|
+
const request = await fetch(url, options);
|
|
488
564
|
if (!request.ok) {
|
|
489
565
|
if (request.status >= 400 && request.status < 500 && request.status !== 429) {
|
|
490
566
|
this.logger.error(
|
|
@@ -832,6 +908,578 @@ class HederaMirrorNode {
|
|
|
832
908
|
return null;
|
|
833
909
|
}
|
|
834
910
|
}
|
|
911
|
+
/**
|
|
912
|
+
* Retrieves token airdrops for a given account ID.
|
|
913
|
+
* @param accountId The ID of the account to retrieve airdrops for.
|
|
914
|
+
* @param limit The maximum number of airdrops to return.
|
|
915
|
+
* @returns A promise that resolves to an array of TokenAirdrop or null.
|
|
916
|
+
*/
|
|
917
|
+
async getTokenAirdrops(accountId, limit = 100) {
|
|
918
|
+
this.logger.info(`Getting token airdrops for account ${accountId}`);
|
|
919
|
+
const url = `${this.baseUrl}/api/v1/accounts/${accountId}/airdrops/tokens?limit=${limit}`;
|
|
920
|
+
try {
|
|
921
|
+
const response = await this._requestWithRetry(url);
|
|
922
|
+
return response.airdrops || [];
|
|
923
|
+
} catch (error) {
|
|
924
|
+
this.logger.error(
|
|
925
|
+
`Error fetching token airdrops for account ${accountId}: ${error.message}`
|
|
926
|
+
);
|
|
927
|
+
return null;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Retrieves blocks from the network.
|
|
932
|
+
* @param options Optional parameters for filtering blocks.
|
|
933
|
+
* @returns A promise that resolves to an array of Block or null.
|
|
934
|
+
*/
|
|
935
|
+
async getBlocks(options) {
|
|
936
|
+
this.logger.info("Getting blocks from the network");
|
|
937
|
+
let url = `${this.baseUrl}/api/v1/blocks`;
|
|
938
|
+
const params = new URLSearchParams();
|
|
939
|
+
if (options?.limit) {
|
|
940
|
+
params.append("limit", options.limit.toString());
|
|
941
|
+
}
|
|
942
|
+
if (options?.order) {
|
|
943
|
+
params.append("order", options.order);
|
|
944
|
+
}
|
|
945
|
+
if (options?.timestamp) {
|
|
946
|
+
params.append("timestamp", options.timestamp);
|
|
947
|
+
}
|
|
948
|
+
if (options?.blockNumber) {
|
|
949
|
+
params.append("block.number", options.blockNumber);
|
|
950
|
+
}
|
|
951
|
+
const queryString = params.toString();
|
|
952
|
+
if (queryString) {
|
|
953
|
+
url += `?${queryString}`;
|
|
954
|
+
}
|
|
955
|
+
try {
|
|
956
|
+
const response = await this._requestWithRetry(url);
|
|
957
|
+
return response.blocks || [];
|
|
958
|
+
} catch (error) {
|
|
959
|
+
this.logger.error(`Error fetching blocks: ${error.message}`);
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Retrieves a specific block by number or hash.
|
|
965
|
+
* @param blockNumberOrHash The block number or hash.
|
|
966
|
+
* @returns A promise that resolves to a Block or null.
|
|
967
|
+
*/
|
|
968
|
+
async getBlock(blockNumberOrHash) {
|
|
969
|
+
this.logger.info(`Getting block ${blockNumberOrHash}`);
|
|
970
|
+
const url = `${this.baseUrl}/api/v1/blocks/${blockNumberOrHash}`;
|
|
971
|
+
try {
|
|
972
|
+
const response = await this._requestWithRetry(url);
|
|
973
|
+
return response;
|
|
974
|
+
} catch (error) {
|
|
975
|
+
this.logger.error(
|
|
976
|
+
`Error fetching block ${blockNumberOrHash}: ${error.message}`
|
|
977
|
+
);
|
|
978
|
+
return null;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Retrieves contract entities from the network.
|
|
983
|
+
* @param options Optional parameters for filtering contracts.
|
|
984
|
+
* @returns A promise that resolves to an array of ContractEntity or null.
|
|
985
|
+
*/
|
|
986
|
+
async getContracts(options) {
|
|
987
|
+
this.logger.info("Getting contracts from the network");
|
|
988
|
+
let url = `${this.baseUrl}/api/v1/contracts`;
|
|
989
|
+
const params = new URLSearchParams();
|
|
990
|
+
if (options?.contractId) {
|
|
991
|
+
params.append("contract.id", options.contractId);
|
|
992
|
+
}
|
|
993
|
+
if (options?.limit) {
|
|
994
|
+
params.append("limit", options.limit.toString());
|
|
995
|
+
}
|
|
996
|
+
if (options?.order) {
|
|
997
|
+
params.append("order", options.order);
|
|
998
|
+
}
|
|
999
|
+
const queryString = params.toString();
|
|
1000
|
+
if (queryString) {
|
|
1001
|
+
url += `?${queryString}`;
|
|
1002
|
+
}
|
|
1003
|
+
try {
|
|
1004
|
+
const response = await this._requestWithRetry(url);
|
|
1005
|
+
return response.contracts || [];
|
|
1006
|
+
} catch (error) {
|
|
1007
|
+
this.logger.error(`Error fetching contracts: ${error.message}`);
|
|
1008
|
+
return null;
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
/**
|
|
1012
|
+
* Retrieves a specific contract by ID or address.
|
|
1013
|
+
* @param contractIdOrAddress The contract ID or EVM address.
|
|
1014
|
+
* @param timestamp Optional timestamp for historical data.
|
|
1015
|
+
* @returns A promise that resolves to a ContractEntity or null.
|
|
1016
|
+
*/
|
|
1017
|
+
async getContract(contractIdOrAddress, timestamp) {
|
|
1018
|
+
this.logger.info(`Getting contract ${contractIdOrAddress}`);
|
|
1019
|
+
let url = `${this.baseUrl}/api/v1/contracts/${contractIdOrAddress}`;
|
|
1020
|
+
if (timestamp) {
|
|
1021
|
+
url += `?timestamp=${timestamp}`;
|
|
1022
|
+
}
|
|
1023
|
+
try {
|
|
1024
|
+
const response = await this._requestWithRetry(url);
|
|
1025
|
+
return response;
|
|
1026
|
+
} catch (error) {
|
|
1027
|
+
this.logger.error(
|
|
1028
|
+
`Error fetching contract ${contractIdOrAddress}: ${error.message}`
|
|
1029
|
+
);
|
|
1030
|
+
return null;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Retrieves contract results from the network.
|
|
1035
|
+
* @param options Optional parameters for filtering contract results.
|
|
1036
|
+
* @returns A promise that resolves to an array of ContractResult or null.
|
|
1037
|
+
*/
|
|
1038
|
+
async getContractResults(options) {
|
|
1039
|
+
this.logger.info("Getting contract results from the network");
|
|
1040
|
+
let url = `${this.baseUrl}/api/v1/contracts/results`;
|
|
1041
|
+
const params = new URLSearchParams();
|
|
1042
|
+
if (options?.from) {
|
|
1043
|
+
params.append("from", options.from);
|
|
1044
|
+
}
|
|
1045
|
+
if (options?.blockHash) {
|
|
1046
|
+
params.append("block.hash", options.blockHash);
|
|
1047
|
+
}
|
|
1048
|
+
if (options?.blockNumber) {
|
|
1049
|
+
params.append("block.number", options.blockNumber);
|
|
1050
|
+
}
|
|
1051
|
+
if (options?.internal !== void 0) {
|
|
1052
|
+
params.append("internal", options.internal.toString());
|
|
1053
|
+
}
|
|
1054
|
+
if (options?.limit) {
|
|
1055
|
+
params.append("limit", options.limit.toString());
|
|
1056
|
+
}
|
|
1057
|
+
if (options?.order) {
|
|
1058
|
+
params.append("order", options.order);
|
|
1059
|
+
}
|
|
1060
|
+
if (options?.timestamp) {
|
|
1061
|
+
params.append("timestamp", options.timestamp);
|
|
1062
|
+
}
|
|
1063
|
+
if (options?.transactionIndex) {
|
|
1064
|
+
params.append("transaction.index", options.transactionIndex.toString());
|
|
1065
|
+
}
|
|
1066
|
+
const queryString = params.toString();
|
|
1067
|
+
if (queryString) {
|
|
1068
|
+
url += `?${queryString}`;
|
|
1069
|
+
}
|
|
1070
|
+
try {
|
|
1071
|
+
const response = await this._requestWithRetry(
|
|
1072
|
+
url
|
|
1073
|
+
);
|
|
1074
|
+
return response.results || [];
|
|
1075
|
+
} catch (error) {
|
|
1076
|
+
this.logger.error(`Error fetching contract results: ${error.message}`);
|
|
1077
|
+
return null;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
/**
|
|
1081
|
+
* Retrieves a specific contract result by transaction ID or hash.
|
|
1082
|
+
* @param transactionIdOrHash The transaction ID or hash.
|
|
1083
|
+
* @param nonce Optional nonce filter.
|
|
1084
|
+
* @returns A promise that resolves to a ContractResult or null.
|
|
1085
|
+
*/
|
|
1086
|
+
async getContractResult(transactionIdOrHash, nonce) {
|
|
1087
|
+
this.logger.info(`Getting contract result for ${transactionIdOrHash}`);
|
|
1088
|
+
let url = `${this.baseUrl}/api/v1/contracts/results/${transactionIdOrHash}`;
|
|
1089
|
+
if (nonce !== void 0) {
|
|
1090
|
+
url += `?nonce=${nonce}`;
|
|
1091
|
+
}
|
|
1092
|
+
try {
|
|
1093
|
+
const response = await this._requestWithRetry(url);
|
|
1094
|
+
return response;
|
|
1095
|
+
} catch (error) {
|
|
1096
|
+
this.logger.error(
|
|
1097
|
+
`Error fetching contract result for ${transactionIdOrHash}: ${error.message}`
|
|
1098
|
+
);
|
|
1099
|
+
return null;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
/**
|
|
1103
|
+
* Retrieves contract results for a specific contract.
|
|
1104
|
+
* @param contractIdOrAddress The contract ID or EVM address.
|
|
1105
|
+
* @param options Optional parameters for filtering.
|
|
1106
|
+
* @returns A promise that resolves to an array of ContractResult or null.
|
|
1107
|
+
*/
|
|
1108
|
+
async getContractResultsByContract(contractIdOrAddress, options) {
|
|
1109
|
+
this.logger.info(
|
|
1110
|
+
`Getting contract results for contract ${contractIdOrAddress}`
|
|
1111
|
+
);
|
|
1112
|
+
let url = `${this.baseUrl}/api/v1/contracts/${contractIdOrAddress}/results`;
|
|
1113
|
+
const params = new URLSearchParams();
|
|
1114
|
+
if (options?.blockHash) {
|
|
1115
|
+
params.append("block.hash", options.blockHash);
|
|
1116
|
+
}
|
|
1117
|
+
if (options?.blockNumber) {
|
|
1118
|
+
params.append("block.number", options.blockNumber);
|
|
1119
|
+
}
|
|
1120
|
+
if (options?.from) {
|
|
1121
|
+
params.append("from", options.from);
|
|
1122
|
+
}
|
|
1123
|
+
if (options?.internal !== void 0) {
|
|
1124
|
+
params.append("internal", options.internal.toString());
|
|
1125
|
+
}
|
|
1126
|
+
if (options?.limit) {
|
|
1127
|
+
params.append("limit", options.limit.toString());
|
|
1128
|
+
}
|
|
1129
|
+
if (options?.order) {
|
|
1130
|
+
params.append("order", options.order);
|
|
1131
|
+
}
|
|
1132
|
+
if (options?.timestamp) {
|
|
1133
|
+
params.append("timestamp", options.timestamp);
|
|
1134
|
+
}
|
|
1135
|
+
if (options?.transactionIndex) {
|
|
1136
|
+
params.append("transaction.index", options.transactionIndex.toString());
|
|
1137
|
+
}
|
|
1138
|
+
const queryString = params.toString();
|
|
1139
|
+
if (queryString) {
|
|
1140
|
+
url += `?${queryString}`;
|
|
1141
|
+
}
|
|
1142
|
+
try {
|
|
1143
|
+
const response = await this._requestWithRetry(
|
|
1144
|
+
url
|
|
1145
|
+
);
|
|
1146
|
+
return response.results || [];
|
|
1147
|
+
} catch (error) {
|
|
1148
|
+
this.logger.error(
|
|
1149
|
+
`Error fetching contract results for ${contractIdOrAddress}: ${error.message}`
|
|
1150
|
+
);
|
|
1151
|
+
return null;
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
/**
|
|
1155
|
+
* Retrieves contract state for a specific contract.
|
|
1156
|
+
* @param contractIdOrAddress The contract ID or EVM address.
|
|
1157
|
+
* @param options Optional parameters for filtering.
|
|
1158
|
+
* @returns A promise that resolves to an array of ContractState or null.
|
|
1159
|
+
*/
|
|
1160
|
+
async getContractState(contractIdOrAddress, options) {
|
|
1161
|
+
this.logger.info(`Getting contract state for ${contractIdOrAddress}`);
|
|
1162
|
+
let url = `${this.baseUrl}/api/v1/contracts/${contractIdOrAddress}/state`;
|
|
1163
|
+
const params = new URLSearchParams();
|
|
1164
|
+
if (options?.limit) {
|
|
1165
|
+
params.append("limit", options.limit.toString());
|
|
1166
|
+
}
|
|
1167
|
+
if (options?.order) {
|
|
1168
|
+
params.append("order", options.order);
|
|
1169
|
+
}
|
|
1170
|
+
if (options?.slot) {
|
|
1171
|
+
params.append("slot", options.slot);
|
|
1172
|
+
}
|
|
1173
|
+
if (options?.timestamp) {
|
|
1174
|
+
params.append("timestamp", options.timestamp);
|
|
1175
|
+
}
|
|
1176
|
+
const queryString = params.toString();
|
|
1177
|
+
if (queryString) {
|
|
1178
|
+
url += `?${queryString}`;
|
|
1179
|
+
}
|
|
1180
|
+
try {
|
|
1181
|
+
const response = await this._requestWithRetry(url);
|
|
1182
|
+
return response.state || [];
|
|
1183
|
+
} catch (error) {
|
|
1184
|
+
this.logger.error(
|
|
1185
|
+
`Error fetching contract state for ${contractIdOrAddress}: ${error.message}`
|
|
1186
|
+
);
|
|
1187
|
+
return null;
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
/**
|
|
1191
|
+
* Retrieves contract actions for a specific transaction.
|
|
1192
|
+
* @param transactionIdOrHash The transaction ID or hash.
|
|
1193
|
+
* @param options Optional parameters for filtering.
|
|
1194
|
+
* @returns A promise that resolves to an array of ContractAction or null.
|
|
1195
|
+
*/
|
|
1196
|
+
async getContractActions(transactionIdOrHash, options) {
|
|
1197
|
+
this.logger.info(`Getting contract actions for ${transactionIdOrHash}`);
|
|
1198
|
+
let url = `${this.baseUrl}/api/v1/contracts/results/${transactionIdOrHash}/actions`;
|
|
1199
|
+
const params = new URLSearchParams();
|
|
1200
|
+
if (options?.index) {
|
|
1201
|
+
params.append("index", options.index);
|
|
1202
|
+
}
|
|
1203
|
+
if (options?.limit) {
|
|
1204
|
+
params.append("limit", options.limit.toString());
|
|
1205
|
+
}
|
|
1206
|
+
if (options?.order) {
|
|
1207
|
+
params.append("order", options.order);
|
|
1208
|
+
}
|
|
1209
|
+
const queryString = params.toString();
|
|
1210
|
+
if (queryString) {
|
|
1211
|
+
url += `?${queryString}`;
|
|
1212
|
+
}
|
|
1213
|
+
try {
|
|
1214
|
+
const response = await this._requestWithRetry(
|
|
1215
|
+
url
|
|
1216
|
+
);
|
|
1217
|
+
return response.actions || [];
|
|
1218
|
+
} catch (error) {
|
|
1219
|
+
this.logger.error(
|
|
1220
|
+
`Error fetching contract actions for ${transactionIdOrHash}: ${error.message}`
|
|
1221
|
+
);
|
|
1222
|
+
return null;
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
/**
|
|
1226
|
+
* Retrieves contract logs from the network.
|
|
1227
|
+
* @param options Optional parameters for filtering logs.
|
|
1228
|
+
* @returns A promise that resolves to an array of ContractLog or null.
|
|
1229
|
+
*/
|
|
1230
|
+
async getContractLogs(options) {
|
|
1231
|
+
this.logger.info("Getting contract logs from the network");
|
|
1232
|
+
let url = `${this.baseUrl}/api/v1/contracts/results/logs`;
|
|
1233
|
+
const params = new URLSearchParams();
|
|
1234
|
+
if (options?.index) {
|
|
1235
|
+
params.append("index", options.index);
|
|
1236
|
+
}
|
|
1237
|
+
if (options?.limit) {
|
|
1238
|
+
params.append("limit", options.limit.toString());
|
|
1239
|
+
}
|
|
1240
|
+
if (options?.order) {
|
|
1241
|
+
params.append("order", options.order);
|
|
1242
|
+
}
|
|
1243
|
+
if (options?.timestamp) {
|
|
1244
|
+
params.append("timestamp", options.timestamp);
|
|
1245
|
+
}
|
|
1246
|
+
if (options?.topic0) {
|
|
1247
|
+
params.append("topic0", options.topic0);
|
|
1248
|
+
}
|
|
1249
|
+
if (options?.topic1) {
|
|
1250
|
+
params.append("topic1", options.topic1);
|
|
1251
|
+
}
|
|
1252
|
+
if (options?.topic2) {
|
|
1253
|
+
params.append("topic2", options.topic2);
|
|
1254
|
+
}
|
|
1255
|
+
if (options?.topic3) {
|
|
1256
|
+
params.append("topic3", options.topic3);
|
|
1257
|
+
}
|
|
1258
|
+
if (options?.transactionHash) {
|
|
1259
|
+
params.append("transaction.hash", options.transactionHash);
|
|
1260
|
+
}
|
|
1261
|
+
const queryString = params.toString();
|
|
1262
|
+
if (queryString) {
|
|
1263
|
+
url += `?${queryString}`;
|
|
1264
|
+
}
|
|
1265
|
+
try {
|
|
1266
|
+
const response = await this._requestWithRetry(url);
|
|
1267
|
+
return response.logs || [];
|
|
1268
|
+
} catch (error) {
|
|
1269
|
+
this.logger.error(`Error fetching contract logs: ${error.message}`);
|
|
1270
|
+
return null;
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
/**
|
|
1274
|
+
* Retrieves contract logs for a specific contract.
|
|
1275
|
+
* @param contractIdOrAddress The contract ID or EVM address.
|
|
1276
|
+
* @param options Optional parameters for filtering logs.
|
|
1277
|
+
* @returns A promise that resolves to an array of ContractLog or null.
|
|
1278
|
+
*/
|
|
1279
|
+
async getContractLogsByContract(contractIdOrAddress, options) {
|
|
1280
|
+
this.logger.info(
|
|
1281
|
+
`Getting contract logs for contract ${contractIdOrAddress}`
|
|
1282
|
+
);
|
|
1283
|
+
let url = `${this.baseUrl}/api/v1/contracts/${contractIdOrAddress}/results/logs`;
|
|
1284
|
+
const params = new URLSearchParams();
|
|
1285
|
+
if (options?.index) {
|
|
1286
|
+
params.append("index", options.index);
|
|
1287
|
+
}
|
|
1288
|
+
if (options?.limit) {
|
|
1289
|
+
params.append("limit", options.limit.toString());
|
|
1290
|
+
}
|
|
1291
|
+
if (options?.order) {
|
|
1292
|
+
params.append("order", options.order);
|
|
1293
|
+
}
|
|
1294
|
+
if (options?.timestamp) {
|
|
1295
|
+
params.append("timestamp", options.timestamp);
|
|
1296
|
+
}
|
|
1297
|
+
if (options?.topic0) {
|
|
1298
|
+
params.append("topic0", options.topic0);
|
|
1299
|
+
}
|
|
1300
|
+
if (options?.topic1) {
|
|
1301
|
+
params.append("topic1", options.topic1);
|
|
1302
|
+
}
|
|
1303
|
+
if (options?.topic2) {
|
|
1304
|
+
params.append("topic2", options.topic2);
|
|
1305
|
+
}
|
|
1306
|
+
if (options?.topic3) {
|
|
1307
|
+
params.append("topic3", options.topic3);
|
|
1308
|
+
}
|
|
1309
|
+
const queryString = params.toString();
|
|
1310
|
+
if (queryString) {
|
|
1311
|
+
url += `?${queryString}`;
|
|
1312
|
+
}
|
|
1313
|
+
try {
|
|
1314
|
+
const response = await this._requestWithRetry(url);
|
|
1315
|
+
return response.logs || [];
|
|
1316
|
+
} catch (error) {
|
|
1317
|
+
this.logger.error(
|
|
1318
|
+
`Error fetching contract logs for ${contractIdOrAddress}: ${error.message}`
|
|
1319
|
+
);
|
|
1320
|
+
return null;
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
/**
|
|
1324
|
+
* Retrieves opcode traces for a specific transaction.
|
|
1325
|
+
* @param transactionIdOrHash The transaction ID or hash.
|
|
1326
|
+
* @param options Optional parameters for trace details.
|
|
1327
|
+
* @returns A promise that resolves to an OpcodeTraceResponse or null.
|
|
1328
|
+
*/
|
|
1329
|
+
async getOpcodeTraces(transactionIdOrHash, options) {
|
|
1330
|
+
this.logger.info(`Getting opcode traces for ${transactionIdOrHash}`);
|
|
1331
|
+
let url = `${this.baseUrl}/api/v1/contracts/results/${transactionIdOrHash}/opcodes`;
|
|
1332
|
+
const params = new URLSearchParams();
|
|
1333
|
+
if (options?.stack !== void 0) {
|
|
1334
|
+
params.append("stack", options.stack.toString());
|
|
1335
|
+
}
|
|
1336
|
+
if (options?.memory !== void 0) {
|
|
1337
|
+
params.append("memory", options.memory.toString());
|
|
1338
|
+
}
|
|
1339
|
+
if (options?.storage !== void 0) {
|
|
1340
|
+
params.append("storage", options.storage.toString());
|
|
1341
|
+
}
|
|
1342
|
+
const queryString = params.toString();
|
|
1343
|
+
if (queryString) {
|
|
1344
|
+
url += `?${queryString}`;
|
|
1345
|
+
}
|
|
1346
|
+
try {
|
|
1347
|
+
const response = await this._requestWithRetry(url);
|
|
1348
|
+
return response;
|
|
1349
|
+
} catch (error) {
|
|
1350
|
+
this.logger.error(
|
|
1351
|
+
`Error fetching opcode traces for ${transactionIdOrHash}: ${error.message}`
|
|
1352
|
+
);
|
|
1353
|
+
return null;
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
/**
|
|
1357
|
+
* Retrieves NFT information by token ID and serial number.
|
|
1358
|
+
* @param tokenId The token ID.
|
|
1359
|
+
* @param serialNumber The serial number of the NFT.
|
|
1360
|
+
* @returns A promise that resolves to an NftInfo or null.
|
|
1361
|
+
*/
|
|
1362
|
+
async getNftInfo(tokenId, serialNumber) {
|
|
1363
|
+
this.logger.info(`Getting NFT info for ${tokenId}/${serialNumber}`);
|
|
1364
|
+
const url = `${this.baseUrl}/api/v1/tokens/${tokenId}/nfts/${serialNumber}`;
|
|
1365
|
+
try {
|
|
1366
|
+
const response = await this._requestWithRetry(url);
|
|
1367
|
+
return response.nft;
|
|
1368
|
+
} catch (error) {
|
|
1369
|
+
this.logger.error(
|
|
1370
|
+
`Error fetching NFT info for ${tokenId}/${serialNumber}: ${error.message}`
|
|
1371
|
+
);
|
|
1372
|
+
return null;
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
/**
|
|
1376
|
+
* Retrieves NFTs for a specific token.
|
|
1377
|
+
* @param tokenId The token ID.
|
|
1378
|
+
* @param options Optional parameters for filtering NFTs.
|
|
1379
|
+
* @returns A promise that resolves to an array of NftInfo or null.
|
|
1380
|
+
*/
|
|
1381
|
+
async getNftsByToken(tokenId, options) {
|
|
1382
|
+
this.logger.info(`Getting NFTs for token ${tokenId}`);
|
|
1383
|
+
let url = `${this.baseUrl}/api/v1/tokens/${tokenId}/nfts`;
|
|
1384
|
+
const params = new URLSearchParams();
|
|
1385
|
+
if (options?.accountId) {
|
|
1386
|
+
params.append("account.id", options.accountId);
|
|
1387
|
+
}
|
|
1388
|
+
if (options?.limit) {
|
|
1389
|
+
params.append("limit", options.limit.toString());
|
|
1390
|
+
}
|
|
1391
|
+
if (options?.order) {
|
|
1392
|
+
params.append("order", options.order);
|
|
1393
|
+
}
|
|
1394
|
+
if (options?.serialNumber) {
|
|
1395
|
+
params.append("serialnumber", options.serialNumber);
|
|
1396
|
+
}
|
|
1397
|
+
const queryString = params.toString();
|
|
1398
|
+
if (queryString) {
|
|
1399
|
+
url += `?${queryString}`;
|
|
1400
|
+
}
|
|
1401
|
+
try {
|
|
1402
|
+
const response = await this._requestWithRetry(url);
|
|
1403
|
+
return response.nfts || [];
|
|
1404
|
+
} catch (error) {
|
|
1405
|
+
this.logger.error(
|
|
1406
|
+
`Error fetching NFTs for token ${tokenId}: ${error.message}`
|
|
1407
|
+
);
|
|
1408
|
+
return null;
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
/**
|
|
1412
|
+
* Retrieves network information.
|
|
1413
|
+
* @returns A promise that resolves to NetworkInfo or null.
|
|
1414
|
+
*/
|
|
1415
|
+
async getNetworkInfo() {
|
|
1416
|
+
this.logger.info("Getting network information");
|
|
1417
|
+
const url = `${this.baseUrl}/api/v1/network/nodes`;
|
|
1418
|
+
try {
|
|
1419
|
+
const response = await this._requestWithRetry(url);
|
|
1420
|
+
return response;
|
|
1421
|
+
} catch (error) {
|
|
1422
|
+
this.logger.error(`Error fetching network info: ${error.message}`);
|
|
1423
|
+
return null;
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Retrieves network fees.
|
|
1428
|
+
* @param timestamp Optional timestamp for historical fees.
|
|
1429
|
+
* @returns A promise that resolves to NetworkFees or null.
|
|
1430
|
+
*/
|
|
1431
|
+
async getNetworkFees(timestamp) {
|
|
1432
|
+
this.logger.info("Getting network fees");
|
|
1433
|
+
let url = `${this.baseUrl}/api/v1/network/fees`;
|
|
1434
|
+
if (timestamp) {
|
|
1435
|
+
url += `?timestamp=${timestamp}`;
|
|
1436
|
+
}
|
|
1437
|
+
try {
|
|
1438
|
+
const response = await this._requestWithRetry(url);
|
|
1439
|
+
return response;
|
|
1440
|
+
} catch (error) {
|
|
1441
|
+
this.logger.error(`Error fetching network fees: ${error.message}`);
|
|
1442
|
+
return null;
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
/**
|
|
1446
|
+
* Retrieves network supply information.
|
|
1447
|
+
* @param timestamp Optional timestamp for historical supply data.
|
|
1448
|
+
* @returns A promise that resolves to NetworkSupply or null.
|
|
1449
|
+
*/
|
|
1450
|
+
async getNetworkSupply(timestamp) {
|
|
1451
|
+
this.logger.info("Getting network supply");
|
|
1452
|
+
let url = `${this.baseUrl}/api/v1/network/supply`;
|
|
1453
|
+
if (timestamp) {
|
|
1454
|
+
url += `?timestamp=${timestamp}`;
|
|
1455
|
+
}
|
|
1456
|
+
try {
|
|
1457
|
+
const response = await this._requestWithRetry(url);
|
|
1458
|
+
return response;
|
|
1459
|
+
} catch (error) {
|
|
1460
|
+
this.logger.error(`Error fetching network supply: ${error.message}`);
|
|
1461
|
+
return null;
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
/**
|
|
1465
|
+
* Retrieves network stake information.
|
|
1466
|
+
* @param timestamp Optional timestamp for historical stake data.
|
|
1467
|
+
* @returns A promise that resolves to NetworkStake or null.
|
|
1468
|
+
*/
|
|
1469
|
+
async getNetworkStake(timestamp) {
|
|
1470
|
+
this.logger.info("Getting network stake");
|
|
1471
|
+
let url = `${this.baseUrl}/api/v1/network/stake`;
|
|
1472
|
+
if (timestamp) {
|
|
1473
|
+
url += `?timestamp=${timestamp}`;
|
|
1474
|
+
}
|
|
1475
|
+
try {
|
|
1476
|
+
const response = await this._requestWithRetry(url);
|
|
1477
|
+
return response;
|
|
1478
|
+
} catch (error) {
|
|
1479
|
+
this.logger.error(`Error fetching network stake: ${error.message}`);
|
|
1480
|
+
return null;
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
835
1483
|
}
|
|
836
1484
|
export {
|
|
837
1485
|
HederaMirrorNode
|