@hiero-ledger/sdk 2.73.2 → 2.75.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/umd.js +368 -202
- package/dist/umd.min.js +3 -3
- package/lib/MirrorNode.cjs +46 -0
- package/lib/MirrorNode.d.ts +16 -0
- package/lib/MirrorNode.js +1 -1
- package/lib/MirrorNode.js.map +1 -1
- package/lib/account/AccountAllowanceApproveTransaction.cjs +11 -5
- package/lib/account/AccountAllowanceApproveTransaction.d.ts +4 -5
- package/lib/account/AccountAllowanceApproveTransaction.js +1 -1
- package/lib/account/AccountAllowanceApproveTransaction.js.map +1 -1
- package/lib/account/TokenAllowance.cjs +4 -2
- package/lib/account/TokenAllowance.d.ts +4 -2
- package/lib/account/TokenAllowance.js +1 -1
- package/lib/account/TokenAllowance.js.map +1 -1
- package/lib/account/TokenTransferMap.cjs +7 -2
- package/lib/account/TokenTransferMap.d.ts +6 -2
- package/lib/account/TokenTransferMap.js +1 -1
- package/lib/account/TokenTransferMap.js.map +1 -1
- package/lib/client/Client.cjs +13 -44
- package/lib/client/Client.d.ts +12 -12
- package/lib/client/Client.js +1 -1
- package/lib/client/Client.js.map +1 -1
- package/lib/client/MirrorNetwork.cjs +16 -0
- package/lib/client/MirrorNetwork.d.ts +7 -0
- package/lib/client/MirrorNetwork.js +1 -1
- package/lib/client/MirrorNetwork.js.map +1 -1
- package/lib/client/addressbooks/mainnet.cjs +1 -1
- package/lib/client/addressbooks/mainnet.d.ts +1 -1
- package/lib/client/addressbooks/mainnet.js +1 -1
- package/lib/client/addressbooks/mainnet.js.map +1 -1
- package/lib/client/addressbooks/previewnet.cjs +1 -1
- package/lib/client/addressbooks/previewnet.d.ts +1 -1
- package/lib/client/addressbooks/previewnet.js +1 -1
- package/lib/client/addressbooks/previewnet.js.map +1 -1
- package/lib/client/addressbooks/testnet.cjs +1 -1
- package/lib/client/addressbooks/testnet.d.ts +1 -1
- package/lib/client/addressbooks/testnet.js +1 -1
- package/lib/client/addressbooks/testnet.js.map +1 -1
- package/lib/constants/ClientConstants.cjs +4 -1
- package/lib/constants/ClientConstants.d.ts +2 -0
- package/lib/constants/ClientConstants.js +1 -1
- package/lib/constants/ClientConstants.js.map +1 -1
- package/lib/contract/ContractId.cjs +2 -5
- package/lib/contract/ContractId.js +1 -1
- package/lib/contract/ContractId.js.map +1 -1
- package/lib/network/AddressBookQueryWeb.cjs +88 -60
- package/lib/network/AddressBookQueryWeb.d.ts +7 -37
- package/lib/network/AddressBookQueryWeb.js +1 -1
- package/lib/network/AddressBookQueryWeb.js.map +1 -1
- package/lib/query/MirrorNodeContractQuery.cjs +2 -1
- package/lib/query/MirrorNodeContractQuery.js.map +1 -1
- package/lib/token/AbstractTokenTransferTransaction.cjs +12 -8
- package/lib/token/AbstractTokenTransferTransaction.d.ts +14 -11
- package/lib/token/AbstractTokenTransferTransaction.js +1 -1
- package/lib/token/AbstractTokenTransferTransaction.js.map +1 -1
- package/lib/token/AssessedCustomFee.cjs +8 -4
- package/lib/token/AssessedCustomFee.d.ts +8 -5
- package/lib/token/AssessedCustomFee.js +1 -1
- package/lib/token/AssessedCustomFee.js.map +1 -1
- package/lib/token/CustomFixedFee.cjs +8 -4
- package/lib/token/CustomFixedFee.d.ts +8 -5
- package/lib/token/CustomFixedFee.js +1 -1
- package/lib/token/CustomFixedFee.js.map +1 -1
- package/lib/token/PendingAirdropRecord.cjs +7 -2
- package/lib/token/PendingAirdropRecord.d.ts +6 -2
- package/lib/token/PendingAirdropRecord.js +1 -1
- package/lib/token/PendingAirdropRecord.js.map +1 -1
- package/lib/token/TokenAirdropTransaction.cjs +2 -1
- package/lib/token/TokenAirdropTransaction.d.ts +4 -2
- package/lib/token/TokenAirdropTransaction.js.map +1 -1
- package/lib/token/TokenBurnTransaction.cjs +5 -3
- package/lib/token/TokenBurnTransaction.d.ts +6 -4
- package/lib/token/TokenBurnTransaction.js +1 -1
- package/lib/token/TokenBurnTransaction.js.map +1 -1
- package/lib/token/TokenCreateTransaction.cjs +7 -6
- package/lib/token/TokenCreateTransaction.d.ts +8 -8
- package/lib/token/TokenCreateTransaction.js +1 -1
- package/lib/token/TokenCreateTransaction.js.map +1 -1
- package/lib/token/TokenMintTransaction.cjs +5 -4
- package/lib/token/TokenMintTransaction.d.ts +6 -5
- package/lib/token/TokenMintTransaction.js +1 -1
- package/lib/token/TokenMintTransaction.js.map +1 -1
- package/lib/token/TokenTransfer.cjs +3 -2
- package/lib/token/TokenTransfer.d.ts +2 -2
- package/lib/token/TokenTransfer.js +1 -1
- package/lib/token/TokenTransfer.js.map +1 -1
- package/lib/token/TokenWipeTransaction.cjs +5 -3
- package/lib/token/TokenWipeTransaction.d.ts +6 -4
- package/lib/token/TokenWipeTransaction.js +1 -1
- package/lib/token/TokenWipeTransaction.js.map +1 -1
- package/lib/transaction/Transaction.cjs +54 -0
- package/lib/transaction/Transaction.d.ts +10 -0
- package/lib/transaction/Transaction.js +1 -1
- package/lib/transaction/Transaction.js.map +1 -1
- package/lib/util.cjs +25 -0
- package/lib/util.d.ts +8 -0
- package/lib/util.js +1 -1
- package/lib/util.js.map +1 -1
- package/lib/version.js +1 -1
- package/package.json +16 -12
- package/src/MirrorNode.js +49 -0
- package/src/account/AccountAllowanceApproveTransaction.js +11 -11
- package/src/account/TokenAllowance.js +5 -2
- package/src/account/TokenTransferMap.js +7 -2
- package/src/client/Client.js +13 -51
- package/src/client/MirrorNetwork.js +18 -0
- package/src/client/addressbooks/mainnet.js +1 -1
- package/src/client/addressbooks/previewnet.js +1 -1
- package/src/client/addressbooks/testnet.js +1 -1
- package/src/constants/ClientConstants.js +3 -0
- package/src/contract/ContractId.js +2 -10
- package/src/network/AddressBookQueryWeb.js +122 -91
- package/src/query/MirrorNodeContractQuery.js +2 -1
- package/src/token/AbstractTokenTransferTransaction.js +12 -8
- package/src/token/AssessedCustomFee.js +8 -5
- package/src/token/CustomFixedFee.js +8 -5
- package/src/token/PendingAirdropRecord.js +7 -2
- package/src/token/TokenAirdropTransaction.js +2 -1
- package/src/token/TokenBurnTransaction.js +5 -3
- package/src/token/TokenCreateTransaction.js +7 -9
- package/src/token/TokenMintTransaction.js +5 -4
- package/src/token/TokenTransfer.js +3 -2
- package/src/token/TokenWipeTransaction.js +5 -3
- package/src/transaction/Transaction.js +63 -0
- package/src/util.js +26 -0
|
@@ -51,8 +51,15 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
51
51
|
* description: string,
|
|
52
52
|
* stake: number
|
|
53
53
|
* }>} nodes
|
|
54
|
+
* @property {?{next: ?string}} links - Links object containing pagination information
|
|
54
55
|
*/
|
|
55
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Default page size limit for optimal pagination performance
|
|
59
|
+
* @constant {number}
|
|
60
|
+
*/
|
|
61
|
+
const DEFAULT_PAGE_SIZE = 25;
|
|
62
|
+
|
|
56
63
|
/**
|
|
57
64
|
* Web-compatible query to get a list of Hedera network node addresses from a mirror node.
|
|
58
65
|
* Uses fetch API instead of gRPC for web environments.
|
|
@@ -67,7 +74,7 @@ class AddressBookQueryWeb extends _Query.default {
|
|
|
67
74
|
/**
|
|
68
75
|
* @param {object} props
|
|
69
76
|
* @param {FileId | string} [props.fileId]
|
|
70
|
-
* @param {number} [props.limit]
|
|
77
|
+
* @param {number} [props.limit] - Page size limit (defaults to 25 for optimal performance)
|
|
71
78
|
*/
|
|
72
79
|
constructor(props = {}) {
|
|
73
80
|
super();
|
|
@@ -215,74 +222,95 @@ class AddressBookQueryWeb extends _Query.default {
|
|
|
215
222
|
if (port) {
|
|
216
223
|
baseUrl = `${baseUrl}:${port}`;
|
|
217
224
|
}
|
|
218
|
-
|
|
225
|
+
|
|
226
|
+
// Initialize aggregated results
|
|
227
|
+
this._addresses = [];
|
|
228
|
+
let nextUrl = null;
|
|
229
|
+
let isLastPage = false;
|
|
230
|
+
|
|
231
|
+
// Build initial URL
|
|
232
|
+
const initialUrl = new URL(`${baseUrl}/api/v1/network/nodes`);
|
|
219
233
|
if (this._fileId != null) {
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
if (this._limit != null) {
|
|
223
|
-
url.searchParams.append("limit", this._limit.toString());
|
|
234
|
+
initialUrl.searchParams.append("file.id", this._fileId.toString());
|
|
224
235
|
}
|
|
225
|
-
for (let attempt = 0; attempt <= this._maxAttempts; attempt++) {
|
|
226
|
-
try {
|
|
227
|
-
// eslint-disable-next-line n/no-unsupported-features/node-builtins
|
|
228
|
-
const response = await fetch(url.toString(), {
|
|
229
|
-
method: "GET",
|
|
230
|
-
headers: {
|
|
231
|
-
Accept: "application/json"
|
|
232
|
-
},
|
|
233
|
-
signal: requestTimeout ? AbortSignal.timeout(requestTimeout) : undefined
|
|
234
|
-
});
|
|
235
|
-
if (!response.ok) {
|
|
236
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
237
|
-
}
|
|
238
236
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
return;
|
|
259
|
-
} catch (error) {
|
|
260
|
-
console.error("Error in _makeFetchRequest:", error);
|
|
261
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
262
|
-
|
|
263
|
-
// Check if we should retry
|
|
264
|
-
if (attempt < this._maxAttempts && !client.isClientShutDown && this._retryHandler(/** @type {MirrorError | Error | null} */error)) {
|
|
265
|
-
const delay = Math.min(250 * 2 ** attempt, this._maxBackoff);
|
|
266
|
-
if (this._logger) {
|
|
267
|
-
this._logger.debug(`Error getting nodes from mirror for file ${this._fileId != null ? this._fileId.toString() : "UNKNOWN"} during attempt ${attempt + 1}. Waiting ${delay} ms before next attempt: ${message}`);
|
|
237
|
+
// Use the specified limit, or default to DEFAULT_PAGE_SIZE for optimal pagination performance
|
|
238
|
+
const effectiveLimit = this._limit != null ? this._limit : DEFAULT_PAGE_SIZE;
|
|
239
|
+
initialUrl.searchParams.append("limit", effectiveLimit.toString());
|
|
240
|
+
|
|
241
|
+
// Fetch all pages
|
|
242
|
+
while (!isLastPage) {
|
|
243
|
+
const currentUrl = nextUrl ? new URL(nextUrl, baseUrl) : initialUrl;
|
|
244
|
+
for (let attempt = 0; attempt <= this._maxAttempts; attempt++) {
|
|
245
|
+
try {
|
|
246
|
+
// eslint-disable-next-line n/no-unsupported-features/node-builtins
|
|
247
|
+
const response = await fetch(currentUrl.toString(), {
|
|
248
|
+
method: "GET",
|
|
249
|
+
headers: {
|
|
250
|
+
Accept: "application/json"
|
|
251
|
+
},
|
|
252
|
+
signal: requestTimeout ? AbortSignal.timeout(requestTimeout) : undefined
|
|
253
|
+
});
|
|
254
|
+
if (!response.ok) {
|
|
255
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
268
256
|
}
|
|
269
257
|
|
|
270
|
-
//
|
|
271
|
-
|
|
272
|
-
await
|
|
273
|
-
|
|
274
|
-
}
|
|
258
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
259
|
+
const data = /** @type {AddressBookQueryWebResponse} */
|
|
260
|
+
await response.json();
|
|
261
|
+
const nodes = data.nodes || [];
|
|
275
262
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
263
|
+
// Aggregate nodes from this page
|
|
264
|
+
const pageNodes = nodes.map(node => _NodeAddress.default.fromJSON({
|
|
265
|
+
nodeId: node.node_id.toString(),
|
|
266
|
+
accountId: node.node_account_id,
|
|
267
|
+
addresses: this._handleAddressesFromGrpcProxyEndpoint(node, client),
|
|
268
|
+
certHash: node.node_cert_hash,
|
|
269
|
+
publicKey: node.public_key,
|
|
270
|
+
description: node.description,
|
|
271
|
+
stake: node.stake.toString()
|
|
272
|
+
}));
|
|
273
|
+
this._addresses.push(...pageNodes);
|
|
274
|
+
nextUrl = data.links?.next || null;
|
|
275
|
+
|
|
276
|
+
// If no more pages, set flag to exit loop
|
|
277
|
+
if (!nextUrl) {
|
|
278
|
+
isLastPage = true;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Move to next page
|
|
282
|
+
break;
|
|
283
|
+
} catch (error) {
|
|
284
|
+
console.error("Error in _makeFetchRequest:", error);
|
|
285
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
286
|
+
|
|
287
|
+
// Check if we should retry
|
|
288
|
+
if (attempt < this._maxAttempts && !client.isClientShutDown && this._retryHandler(/** @type {MirrorError | Error | null} */error)) {
|
|
289
|
+
const delay = Math.min(250 * 2 ** attempt, this._maxBackoff);
|
|
290
|
+
if (this._logger) {
|
|
291
|
+
this._logger.debug(`Error getting nodes from mirror for file ${this._fileId != null ? this._fileId.toString() : "UNKNOWN"} during attempt ${attempt + 1}. Waiting ${delay} ms before next attempt: ${message}`);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Wait before next attempt
|
|
295
|
+
// eslint-disable-next-line ie11/no-loop-func
|
|
296
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// If we shouldn't retry or have exhausted attempts, reject
|
|
301
|
+
const maxAttemptsReached = attempt >= this._maxAttempts;
|
|
302
|
+
const errorMessage = maxAttemptsReached ? `Failed to query address book after ${this._maxAttempts + 1} attempts. Last error: ${message}` : `Failed to query address book: ${message}`;
|
|
303
|
+
reject(new Error(errorMessage));
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
281
306
|
}
|
|
282
307
|
}
|
|
283
308
|
|
|
284
|
-
//
|
|
285
|
-
|
|
309
|
+
// Return the aggregated results
|
|
310
|
+
const addressBook = new _NodeAddressBook.default({
|
|
311
|
+
nodeAddresses: this._addresses
|
|
312
|
+
});
|
|
313
|
+
resolve(addressBook);
|
|
286
314
|
}
|
|
287
315
|
|
|
288
316
|
/**
|
|
@@ -1,39 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {import("../channel/Channel.js").default} Channel
|
|
3
|
-
* @typedef {import("../channel/MirrorChannel.js").default} MirrorChannel
|
|
4
|
-
* @typedef {import("../channel/MirrorChannel.js").MirrorError} MirrorError
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* @template {Channel} ChannelT
|
|
8
|
-
* @typedef {import("../client/Client.js").default<ChannelT, MirrorChannel>} Client<ChannelT, MirrorChannel>
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* @typedef {object} EndpointWebResponse
|
|
12
|
-
* @property {string} domain_name
|
|
13
|
-
* @property {string} ip_address_v4
|
|
14
|
-
* @property {number} port
|
|
15
|
-
*/
|
|
16
|
-
/**
|
|
17
|
-
* @typedef {object} AddressBookQueryWebResponse
|
|
18
|
-
* @property {Array<{
|
|
19
|
-
* admin_key: {
|
|
20
|
-
* key: string,
|
|
21
|
-
* _type: string,
|
|
22
|
-
* },
|
|
23
|
-
* decline_reward: boolean,
|
|
24
|
-
* grpc_proxy_endpoint: EndpointWebResponse,
|
|
25
|
-
* file_id: string,
|
|
26
|
-
* memo: string,
|
|
27
|
-
* public_key: string,
|
|
28
|
-
* node_id: number,
|
|
29
|
-
* node_account_id: string,
|
|
30
|
-
* node_cert_hash: string,
|
|
31
|
-
* address: string,
|
|
32
|
-
* service_endpoints: EndpointWebResponse[],
|
|
33
|
-
* description: string,
|
|
34
|
-
* stake: number
|
|
35
|
-
* }>} nodes
|
|
36
|
-
*/
|
|
37
1
|
/**
|
|
38
2
|
* Web-compatible query to get a list of Hedera network node addresses from a mirror node.
|
|
39
3
|
* Uses fetch API instead of gRPC for web environments.
|
|
@@ -48,7 +12,7 @@ export default class AddressBookQueryWeb extends Query<NodeAddressBook> {
|
|
|
48
12
|
/**
|
|
49
13
|
* @param {object} props
|
|
50
14
|
* @param {FileId | string} [props.fileId]
|
|
51
|
-
* @param {number} [props.limit]
|
|
15
|
+
* @param {number} [props.limit] - Page size limit (defaults to 25 for optimal performance)
|
|
52
16
|
*/
|
|
53
17
|
constructor(props?: {
|
|
54
18
|
fileId?: string | FileId | undefined;
|
|
@@ -158,6 +122,12 @@ export type AddressBookQueryWebResponse = {
|
|
|
158
122
|
description: string;
|
|
159
123
|
stake: number;
|
|
160
124
|
}>;
|
|
125
|
+
/**
|
|
126
|
+
* - Links object containing pagination information
|
|
127
|
+
*/
|
|
128
|
+
links: {
|
|
129
|
+
next: string | null;
|
|
130
|
+
} | null;
|
|
161
131
|
};
|
|
162
132
|
import NodeAddressBook from "../address_book/NodeAddressBook.js";
|
|
163
133
|
import Query from "../query/Query.js";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import t from"../query/Query.js";import e from"../address_book/NodeAddressBook.js";import
|
|
1
|
+
import t from"../query/Query.js";import e from"../address_book/NodeAddressBook.js";import s from"../file/FileId.js";import{RST_STREAM as r}from"../Executable.js";import i from"../address_book/NodeAddress.js";import{MAINNET as o,WEB_TESTNET as n,WEB_PREVIEWNET as d}from"../constants/ClientConstants.js";class a extends t{constructor(t={}){super(),this._fileId=null,null!=t.fileId&&this.setFileId(t.fileId),this._limit=null,null!=t.limit&&this.setLimit(t.limit),this._retryHandler=t=>{if(null!=t){if(t instanceof Error)return!0;switch(t.code){case 13:return r.test(t.details.toString());case 5:case 8:case 14:case 17:return!0;default:return!1}}return!1},this._addresses=[]}get fileId(){return this._fileId}setFileId(t){return this._fileId="string"==typeof t?s.fromString(t):t.clone(),this}get limit(){return this._limit}setLimit(t){return this._limit=t,this}setMaxAttempts(t){return this._maxAttempts=t,this}setMaxBackoff(t){return this._maxBackoff=t,this}execute(t,e){if(0===t._network._network.size&&!t._timer)throw new Error("The client's network update period is required. Please set it using the setNetworkUpdatePeriod method.");return new Promise((s,r)=>{this._makeFetchRequest(t,s,r,e)})}async _makeFetchRequest(t,s,r,o){const{port:n,address:d}=t._mirrorNetwork.getNextMirrorNode().address;let a=`${d.includes("127.0.0.1")||d.includes("localhost")?"http":"https"}://${d}`;n&&(a=`${a}:${n}`),this._addresses=[];let l=null,c=!1;const m=new URL(`${a}/api/v1/network/nodes`);null!=this._fileId&&m.searchParams.append("file.id",this._fileId.toString());const h=null!=this._limit?this._limit:25;for(m.searchParams.append("limit",h.toString());!c;){const e=l?new URL(l,a):m;for(let s=0;s<=this._maxAttempts;s++)try{const s=await fetch(e.toString(),{method:"GET",headers:{Accept:"application/json"},signal:o?AbortSignal.timeout(o):void 0});if(!s.ok)throw new Error(`HTTP error! status: ${s.status}`);const r=await s.json(),n=(r.nodes||[]).map(e=>i.fromJSON({nodeId:e.node_id.toString(),accountId:e.node_account_id,addresses:this._handleAddressesFromGrpcProxyEndpoint(e,t),certHash:e.node_cert_hash,publicKey:e.public_key,description:e.description,stake:e.stake.toString()}));this._addresses.push(...n),l=r.links?.next||null,l||(c=!0);break}catch(e){console.error("Error in _makeFetchRequest:",e);const i=e instanceof Error?e.message:String(e);if(s<this._maxAttempts&&!t.isClientShutDown&&this._retryHandler(e)){const t=Math.min(250*2**s,this._maxBackoff);this._logger&&this._logger.debug(`Error getting nodes from mirror for file ${null!=this._fileId?this._fileId.toString():"UNKNOWN"} during attempt ${s+1}. Waiting ${t} ms before next attempt: ${i}`),await new Promise(e=>setTimeout(e,t));continue}const o=s>=this._maxAttempts?`Failed to query address book after ${this._maxAttempts+1} attempts. Last error: ${i}`:`Failed to query address book: ${i}`;return void r(new Error(o))}}s(new e({nodeAddresses:this._addresses}))}_handleAddressesFromGrpcProxyEndpoint(t,e){const s=t.grpc_proxy_endpoint;if(s&&s.domain_name&&s.port)return[{address:s.domain_name,port:s.port.toString()}];let r;const i=e._network.ledgerId;if(i&&i.isMainnet())r=o;else if(i&&i.isTestnet())r=n;else{if(!i||!i.isPreviewnet())return[];r=d}const a=t.node_account_id;for(const[t,e]of Object.entries(r))if(e.toString()===a){const[e,s]=t.split(":");return[{address:e,port:s}]}return[]}}export{a as default};
|
|
2
2
|
//# sourceMappingURL=AddressBookQueryWeb.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AddressBookQueryWeb.js","sources":["../../src/network/AddressBookQueryWeb.js"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\nimport Query from \"../query/Query.js\";\nimport NodeAddressBook from \"../address_book/NodeAddressBook.js\";\nimport FileId from \"../file/FileId.js\";\nimport { RST_STREAM } from \"../Executable.js\";\nimport NodeAddress from \"../address_book/NodeAddress.js\";\nimport {\n MAINNET,\n WEB_TESTNET,\n WEB_PREVIEWNET,\n} from \"../constants/ClientConstants.js\";\n\n/**\n * @typedef {import(\"../channel/Channel.js\").default} Channel\n * @typedef {import(\"../channel/MirrorChannel.js\").default} MirrorChannel\n * @typedef {import(\"../channel/MirrorChannel.js\").MirrorError} MirrorError\n */\n\n/**\n * @template {Channel} ChannelT\n * @typedef {import(\"../client/Client.js\").default<ChannelT, MirrorChannel>} Client<ChannelT, MirrorChannel>\n */\n\n/**\n * @typedef {object} EndpointWebResponse\n * @property {string} domain_name\n * @property {string} ip_address_v4\n * @property {number} port\n */\n\n/**\n * @typedef {object} AddressBookQueryWebResponse\n * @property {Array<{\n * admin_key: {\n * key: string,\n * _type: string,\n * },\n * decline_reward: boolean,\n * grpc_proxy_endpoint: EndpointWebResponse,\n * file_id: string,\n * memo: string,\n * public_key: string,\n * node_id: number,\n * node_account_id: string,\n * node_cert_hash: string,\n * address: string,\n * service_endpoints: EndpointWebResponse[],\n * description: string,\n * stake: number\n * }>} nodes\n */\n\n/**\n * Web-compatible query to get a list of Hedera network node addresses from a mirror node.\n * Uses fetch API instead of gRPC for web environments.\n *\n * This query can be used to retrieve node addresses either from a specific file ID\n * or from the most recent address book if no file ID is specified. The response\n * contains node metadata including IP addresses and ports for both node and mirror\n * node services.\n * @augments {Query<NodeAddressBook>}\n */\nexport default class AddressBookQueryWeb extends Query {\n /**\n * @param {object} props\n * @param {FileId | string} [props.fileId]\n * @param {number} [props.limit]\n */\n constructor(props = {}) {\n super();\n\n /**\n * @private\n * @type {?FileId}\n */\n this._fileId = null;\n if (props.fileId != null) {\n this.setFileId(props.fileId);\n }\n\n /**\n * Page limit for the query\n * @private\n * @type {?number}\n */\n this._limit = null;\n if (props.limit != null) {\n this.setLimit(props.limit);\n }\n\n /**\n * @private\n * @type {(error: MirrorError | Error | null) => boolean}\n */\n this._retryHandler = (error) => {\n if (error != null) {\n if (error instanceof Error) {\n // Retry on all errors which are not `MirrorError` because they're\n // likely lower level HTTP errors\n return true;\n } else {\n // Retry on `NOT_FOUND`, `RESOURCE_EXHAUSTED`, `UNAVAILABLE`, and conditionally on `INTERNAL`\n // if the message matches the right regex.\n switch (error.code) {\n // INTERNAL\n // eslint-disable-next-line no-fallthrough\n case 13:\n return RST_STREAM.test(error.details.toString());\n // NOT_FOUND\n // eslint-disable-next-line no-fallthrough\n case 5:\n // RESOURCE_EXHAUSTED\n // eslint-disable-next-line no-fallthrough\n case 8:\n // UNAVAILABLE\n // eslint-disable-next-line no-fallthrough\n case 14:\n case 17:\n return true;\n default:\n return false;\n }\n }\n }\n\n return false;\n };\n\n /** @type {NodeAddress[]} */\n this._addresses = [];\n }\n\n /**\n * @returns {?FileId}\n */\n get fileId() {\n return this._fileId;\n }\n\n /**\n * @param {FileId | string} fileId\n * @returns {AddressBookQueryWeb}\n */\n setFileId(fileId) {\n this._fileId =\n typeof fileId === \"string\"\n ? FileId.fromString(fileId)\n : fileId.clone();\n\n return this;\n }\n\n /**\n * Page limit for the query\n * @returns {?number}\n */\n get limit() {\n return this._limit;\n }\n\n /**\n * Set the page limit for the query\n * @param {number} limit\n * @returns {AddressBookQueryWeb}\n */\n setLimit(limit) {\n this._limit = limit;\n\n return this;\n }\n\n /**\n * @param {number} attempts\n * @returns {this}\n */\n setMaxAttempts(attempts) {\n this._maxAttempts = attempts;\n return this;\n }\n\n /**\n * @param {number} backoff\n * @returns {this}\n */\n setMaxBackoff(backoff) {\n this._maxBackoff = backoff;\n return this;\n }\n\n /**\n * @param {Client<Channel>} client\n * @param {number=} requestTimeout\n * @returns {Promise<NodeAddressBook>}\n */\n execute(client, requestTimeout) {\n // Extra validation when initializing the client with only a mirror network\n if (client._network._network.size === 0 && !client._timer) {\n throw new Error(\n \"The client's network update period is required. Please set it using the setNetworkUpdatePeriod method.\",\n );\n }\n\n return new Promise((resolve, reject) => {\n void this._makeFetchRequest(\n client,\n resolve,\n reject,\n requestTimeout,\n );\n });\n }\n\n /**\n * @private\n * @param {Client<Channel>} client\n * @param {(value: NodeAddressBook) => void} resolve\n * @param {(error: Error) => void} reject\n * @param {number=} requestTimeout\n */\n async _makeFetchRequest(client, resolve, reject, requestTimeout) {\n const { port, address } =\n client._mirrorNetwork.getNextMirrorNode().address;\n\n let baseUrl = `${\n address.includes(\"127.0.0.1\") || address.includes(\"localhost\")\n ? \"http\"\n : \"https\"\n }://${address}`;\n\n if (port) {\n baseUrl = `${baseUrl}:${port}`;\n }\n\n const url = new URL(`${baseUrl}/api/v1/network/nodes`);\n\n if (this._fileId != null) {\n url.searchParams.append(\"file.id\", this._fileId.toString());\n }\n if (this._limit != null) {\n url.searchParams.append(\"limit\", this._limit.toString());\n }\n\n for (let attempt = 0; attempt <= this._maxAttempts; attempt++) {\n try {\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n const response = await fetch(url.toString(), {\n method: \"GET\",\n headers: {\n Accept: \"application/json\",\n },\n signal: requestTimeout\n ? AbortSignal.timeout(requestTimeout)\n : undefined,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const data = /** @type {AddressBookQueryWebResponse} */ (\n await response.json()\n );\n\n const nodes = data.nodes || [];\n\n // eslint-disable-next-line ie11/no-loop-func\n this._addresses = nodes.map((node) =>\n NodeAddress.fromJSON({\n nodeId: node.node_id.toString(),\n accountId: node.node_account_id,\n addresses: this._handleAddressesFromGrpcProxyEndpoint(\n node,\n client,\n ),\n certHash: node.node_cert_hash,\n publicKey: node.public_key,\n description: node.description,\n stake: node.stake.toString(),\n }),\n );\n\n const addressBook = new NodeAddressBook({\n nodeAddresses: this._addresses,\n });\n\n resolve(addressBook);\n return;\n } catch (error) {\n console.error(\"Error in _makeFetchRequest:\", error);\n const message =\n error instanceof Error ? error.message : String(error);\n\n // Check if we should retry\n if (\n attempt < this._maxAttempts &&\n !client.isClientShutDown &&\n this._retryHandler(\n /** @type {MirrorError | Error | null} */ (error),\n )\n ) {\n const delay = Math.min(\n 250 * 2 ** attempt,\n this._maxBackoff,\n );\n\n if (this._logger) {\n this._logger.debug(\n `Error getting nodes from mirror for file ${\n this._fileId != null\n ? this._fileId.toString()\n : \"UNKNOWN\"\n } during attempt ${\n attempt + 1\n }. Waiting ${delay} ms before next attempt: ${message}`,\n );\n }\n\n // Wait before next attempt\n // eslint-disable-next-line ie11/no-loop-func\n await new Promise((resolve) => setTimeout(resolve, delay));\n continue;\n }\n\n // If we shouldn't retry or have exhausted attempts, reject\n const maxAttemptsReached = attempt >= this._maxAttempts;\n const errorMessage = maxAttemptsReached\n ? `Failed to query address book after ${\n this._maxAttempts + 1\n } attempts. Last error: ${message}`\n : `Failed to query address book: ${message}`;\n reject(new Error(errorMessage));\n return;\n }\n }\n\n // This should never be reached, but just in case\n reject(new Error(\"failed to query address book\"));\n }\n\n /**\n * Handles the grpc_proxy_endpoint fallback logic for a node.\n * @param {AddressBookQueryWebResponse['nodes'][number]} node - The node object from the mirror node response.\n * @param {Client<Channel>} client - The client instance.\n * @returns {Array<{address: string, port: string}>}\n */\n _handleAddressesFromGrpcProxyEndpoint(node, client) {\n const grpcProxyEndpoint = node.grpc_proxy_endpoint;\n\n if (\n grpcProxyEndpoint &&\n grpcProxyEndpoint.domain_name &&\n grpcProxyEndpoint.port\n ) {\n return [\n {\n address: grpcProxyEndpoint.domain_name,\n port: grpcProxyEndpoint.port.toString(),\n },\n ];\n }\n\n let networkConstant;\n const ledgerId = client._network.ledgerId;\n\n if (ledgerId && ledgerId.isMainnet()) {\n networkConstant = MAINNET;\n } else if (ledgerId && ledgerId.isTestnet()) {\n networkConstant = WEB_TESTNET;\n } else if (ledgerId && ledgerId.isPreviewnet()) {\n networkConstant = WEB_PREVIEWNET;\n } else {\n return [];\n }\n\n const nodeAccountId = node.node_account_id;\n\n for (const [address, accountIdObj] of Object.entries(networkConstant)) {\n if (accountIdObj.toString() === nodeAccountId) {\n const [domain_name, port] = address.split(\":\");\n\n return [\n {\n address: domain_name,\n port,\n },\n ];\n }\n }\n\n return [];\n }\n}\n"],"names":["AddressBookQueryWeb","Query","constructor","props","super","this","_fileId","fileId","setFileId","_limit","limit","setLimit","_retryHandler","error","Error","code","RST_STREAM","test","details","toString","_addresses","FileId","fromString","clone","setMaxAttempts","attempts","_maxAttempts","setMaxBackoff","backoff","_maxBackoff","execute","client","requestTimeout","_network","size","_timer","Promise","resolve","reject","_makeFetchRequest","port","address","_mirrorNetwork","getNextMirrorNode","baseUrl","includes","url","URL","searchParams","append","attempt","response","fetch","method","headers","Accept","signal","AbortSignal","timeout","undefined","ok","status","nodes","json","map","node","NodeAddress","fromJSON","nodeId","node_id","accountId","node_account_id","addresses","_handleAddressesFromGrpcProxyEndpoint","certHash","node_cert_hash","publicKey","public_key","description","stake","NodeAddressBook","nodeAddresses","console","message","String","isClientShutDown","delay","Math","min","_logger","debug","setTimeout","errorMessage","grpcProxyEndpoint","grpc_proxy_endpoint","domain_name","networkConstant","ledgerId","isMainnet","MAINNET","isTestnet","WEB_TESTNET","isPreviewnet","WEB_PREVIEWNET","nodeAccountId","accountIdObj","Object","entries","split"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AddressBookQueryWeb.js","sources":["../../src/network/AddressBookQueryWeb.js"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\nimport Query from \"../query/Query.js\";\nimport NodeAddressBook from \"../address_book/NodeAddressBook.js\";\nimport FileId from \"../file/FileId.js\";\nimport { RST_STREAM } from \"../Executable.js\";\nimport NodeAddress from \"../address_book/NodeAddress.js\";\nimport {\n MAINNET,\n WEB_TESTNET,\n WEB_PREVIEWNET,\n} from \"../constants/ClientConstants.js\";\n\n/**\n * @typedef {import(\"../channel/Channel.js\").default} Channel\n * @typedef {import(\"../channel/MirrorChannel.js\").default} MirrorChannel\n * @typedef {import(\"../channel/MirrorChannel.js\").MirrorError} MirrorError\n */\n\n/**\n * @template {Channel} ChannelT\n * @typedef {import(\"../client/Client.js\").default<ChannelT, MirrorChannel>} Client<ChannelT, MirrorChannel>\n */\n\n/**\n * @typedef {object} EndpointWebResponse\n * @property {string} domain_name\n * @property {string} ip_address_v4\n * @property {number} port\n */\n\n/**\n * @typedef {object} AddressBookQueryWebResponse\n * @property {Array<{\n * admin_key: {\n * key: string,\n * _type: string,\n * },\n * decline_reward: boolean,\n * grpc_proxy_endpoint: EndpointWebResponse,\n * file_id: string,\n * memo: string,\n * public_key: string,\n * node_id: number,\n * node_account_id: string,\n * node_cert_hash: string,\n * address: string,\n * service_endpoints: EndpointWebResponse[],\n * description: string,\n * stake: number\n * }>} nodes\n * @property {?{next: ?string}} links - Links object containing pagination information\n */\n\n/**\n * Default page size limit for optimal pagination performance\n * @constant {number}\n */\nconst DEFAULT_PAGE_SIZE = 25;\n\n/**\n * Web-compatible query to get a list of Hedera network node addresses from a mirror node.\n * Uses fetch API instead of gRPC for web environments.\n *\n * This query can be used to retrieve node addresses either from a specific file ID\n * or from the most recent address book if no file ID is specified. The response\n * contains node metadata including IP addresses and ports for both node and mirror\n * node services.\n * @augments {Query<NodeAddressBook>}\n */\nexport default class AddressBookQueryWeb extends Query {\n /**\n * @param {object} props\n * @param {FileId | string} [props.fileId]\n * @param {number} [props.limit] - Page size limit (defaults to 25 for optimal performance)\n */\n constructor(props = {}) {\n super();\n\n /**\n * @private\n * @type {?FileId}\n */\n this._fileId = null;\n if (props.fileId != null) {\n this.setFileId(props.fileId);\n }\n\n /**\n * Page limit for the query\n * @private\n * @type {?number}\n */\n this._limit = null;\n if (props.limit != null) {\n this.setLimit(props.limit);\n }\n\n /**\n * @private\n * @type {(error: MirrorError | Error | null) => boolean}\n */\n this._retryHandler = (error) => {\n if (error != null) {\n if (error instanceof Error) {\n // Retry on all errors which are not `MirrorError` because they're\n // likely lower level HTTP errors\n return true;\n } else {\n // Retry on `NOT_FOUND`, `RESOURCE_EXHAUSTED`, `UNAVAILABLE`, and conditionally on `INTERNAL`\n // if the message matches the right regex.\n switch (error.code) {\n // INTERNAL\n // eslint-disable-next-line no-fallthrough\n case 13:\n return RST_STREAM.test(error.details.toString());\n // NOT_FOUND\n // eslint-disable-next-line no-fallthrough\n case 5:\n // RESOURCE_EXHAUSTED\n // eslint-disable-next-line no-fallthrough\n case 8:\n // UNAVAILABLE\n // eslint-disable-next-line no-fallthrough\n case 14:\n case 17:\n return true;\n default:\n return false;\n }\n }\n }\n\n return false;\n };\n\n /** @type {NodeAddress[]} */\n this._addresses = [];\n }\n\n /**\n * @returns {?FileId}\n */\n get fileId() {\n return this._fileId;\n }\n\n /**\n * @param {FileId | string} fileId\n * @returns {AddressBookQueryWeb}\n */\n setFileId(fileId) {\n this._fileId =\n typeof fileId === \"string\"\n ? FileId.fromString(fileId)\n : fileId.clone();\n\n return this;\n }\n\n /**\n * Page limit for the query\n * @returns {?number}\n */\n get limit() {\n return this._limit;\n }\n\n /**\n * Set the page limit for the query\n * @param {number} limit\n * @returns {AddressBookQueryWeb}\n */\n setLimit(limit) {\n this._limit = limit;\n\n return this;\n }\n\n /**\n * @param {number} attempts\n * @returns {this}\n */\n setMaxAttempts(attempts) {\n this._maxAttempts = attempts;\n return this;\n }\n\n /**\n * @param {number} backoff\n * @returns {this}\n */\n setMaxBackoff(backoff) {\n this._maxBackoff = backoff;\n return this;\n }\n\n /**\n * @param {Client<Channel>} client\n * @param {number=} requestTimeout\n * @returns {Promise<NodeAddressBook>}\n */\n execute(client, requestTimeout) {\n // Extra validation when initializing the client with only a mirror network\n if (client._network._network.size === 0 && !client._timer) {\n throw new Error(\n \"The client's network update period is required. Please set it using the setNetworkUpdatePeriod method.\",\n );\n }\n\n return new Promise((resolve, reject) => {\n void this._makeFetchRequest(\n client,\n resolve,\n reject,\n requestTimeout,\n );\n });\n }\n\n /**\n * @private\n * @param {Client<Channel>} client\n * @param {(value: NodeAddressBook) => void} resolve\n * @param {(error: Error) => void} reject\n * @param {number=} requestTimeout\n */\n async _makeFetchRequest(client, resolve, reject, requestTimeout) {\n const { port, address } =\n client._mirrorNetwork.getNextMirrorNode().address;\n\n let baseUrl = `${\n address.includes(\"127.0.0.1\") || address.includes(\"localhost\")\n ? \"http\"\n : \"https\"\n }://${address}`;\n\n if (port) {\n baseUrl = `${baseUrl}:${port}`;\n }\n\n // Initialize aggregated results\n this._addresses = [];\n let nextUrl = null;\n let isLastPage = false;\n\n // Build initial URL\n const initialUrl = new URL(`${baseUrl}/api/v1/network/nodes`);\n if (this._fileId != null) {\n initialUrl.searchParams.append(\"file.id\", this._fileId.toString());\n }\n\n // Use the specified limit, or default to DEFAULT_PAGE_SIZE for optimal pagination performance\n const effectiveLimit =\n this._limit != null ? this._limit : DEFAULT_PAGE_SIZE;\n initialUrl.searchParams.append(\"limit\", effectiveLimit.toString());\n\n // Fetch all pages\n while (!isLastPage) {\n const currentUrl = nextUrl ? new URL(nextUrl, baseUrl) : initialUrl;\n\n for (let attempt = 0; attempt <= this._maxAttempts; attempt++) {\n try {\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n const response = await fetch(currentUrl.toString(), {\n method: \"GET\",\n headers: {\n Accept: \"application/json\",\n },\n signal: requestTimeout\n ? AbortSignal.timeout(requestTimeout)\n : undefined,\n });\n\n if (!response.ok) {\n throw new Error(\n `HTTP error! status: ${response.status}`,\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const data = /** @type {AddressBookQueryWebResponse} */ (\n await response.json()\n );\n\n const nodes = data.nodes || [];\n\n // Aggregate nodes from this page\n const pageNodes = nodes.map((node) =>\n NodeAddress.fromJSON({\n nodeId: node.node_id.toString(),\n accountId: node.node_account_id,\n addresses:\n this._handleAddressesFromGrpcProxyEndpoint(\n node,\n client,\n ),\n certHash: node.node_cert_hash,\n publicKey: node.public_key,\n description: node.description,\n stake: node.stake.toString(),\n }),\n );\n\n this._addresses.push(...pageNodes);\n nextUrl = data.links?.next || null;\n\n // If no more pages, set flag to exit loop\n if (!nextUrl) {\n isLastPage = true;\n }\n\n // Move to next page\n break;\n } catch (error) {\n console.error(\"Error in _makeFetchRequest:\", error);\n const message =\n error instanceof Error ? error.message : String(error);\n\n // Check if we should retry\n if (\n attempt < this._maxAttempts &&\n !client.isClientShutDown &&\n this._retryHandler(\n /** @type {MirrorError | Error | null} */ (error),\n )\n ) {\n const delay = Math.min(\n 250 * 2 ** attempt,\n this._maxBackoff,\n );\n\n if (this._logger) {\n this._logger.debug(\n `Error getting nodes from mirror for file ${\n this._fileId != null\n ? this._fileId.toString()\n : \"UNKNOWN\"\n } during attempt ${\n attempt + 1\n }. Waiting ${delay} ms before next attempt: ${message}`,\n );\n }\n\n // Wait before next attempt\n // eslint-disable-next-line ie11/no-loop-func\n await new Promise((resolve) =>\n setTimeout(resolve, delay),\n );\n continue;\n }\n\n // If we shouldn't retry or have exhausted attempts, reject\n const maxAttemptsReached = attempt >= this._maxAttempts;\n const errorMessage = maxAttemptsReached\n ? `Failed to query address book after ${\n this._maxAttempts + 1\n } attempts. Last error: ${message}`\n : `Failed to query address book: ${message}`;\n reject(new Error(errorMessage));\n return;\n }\n }\n }\n\n // Return the aggregated results\n const addressBook = new NodeAddressBook({\n nodeAddresses: this._addresses,\n });\n resolve(addressBook);\n }\n\n /**\n * Handles the grpc_proxy_endpoint fallback logic for a node.\n * @param {AddressBookQueryWebResponse['nodes'][number]} node - The node object from the mirror node response.\n * @param {Client<Channel>} client - The client instance.\n * @returns {Array<{address: string, port: string}>}\n */\n _handleAddressesFromGrpcProxyEndpoint(node, client) {\n const grpcProxyEndpoint = node.grpc_proxy_endpoint;\n\n if (\n grpcProxyEndpoint &&\n grpcProxyEndpoint.domain_name &&\n grpcProxyEndpoint.port\n ) {\n return [\n {\n address: grpcProxyEndpoint.domain_name,\n port: grpcProxyEndpoint.port.toString(),\n },\n ];\n }\n\n let networkConstant;\n const ledgerId = client._network.ledgerId;\n\n if (ledgerId && ledgerId.isMainnet()) {\n networkConstant = MAINNET;\n } else if (ledgerId && ledgerId.isTestnet()) {\n networkConstant = WEB_TESTNET;\n } else if (ledgerId && ledgerId.isPreviewnet()) {\n networkConstant = WEB_PREVIEWNET;\n } else {\n return [];\n }\n\n const nodeAccountId = node.node_account_id;\n\n for (const [address, accountIdObj] of Object.entries(networkConstant)) {\n if (accountIdObj.toString() === nodeAccountId) {\n const [domain_name, port] = address.split(\":\");\n\n return [\n {\n address: domain_name,\n port,\n },\n ];\n }\n }\n\n return [];\n }\n}\n"],"names":["AddressBookQueryWeb","Query","constructor","props","super","this","_fileId","fileId","setFileId","_limit","limit","setLimit","_retryHandler","error","Error","code","RST_STREAM","test","details","toString","_addresses","FileId","fromString","clone","setMaxAttempts","attempts","_maxAttempts","setMaxBackoff","backoff","_maxBackoff","execute","client","requestTimeout","_network","size","_timer","Promise","resolve","reject","_makeFetchRequest","port","address","_mirrorNetwork","getNextMirrorNode","baseUrl","includes","nextUrl","isLastPage","initialUrl","URL","searchParams","append","effectiveLimit","currentUrl","attempt","response","fetch","method","headers","Accept","signal","AbortSignal","timeout","undefined","ok","status","data","json","pageNodes","nodes","map","node","NodeAddress","fromJSON","nodeId","node_id","accountId","node_account_id","addresses","_handleAddressesFromGrpcProxyEndpoint","certHash","node_cert_hash","publicKey","public_key","description","stake","push","links","next","console","message","String","isClientShutDown","delay","Math","min","_logger","debug","setTimeout","errorMessage","NodeAddressBook","nodeAddresses","grpcProxyEndpoint","grpc_proxy_endpoint","domain_name","networkConstant","ledgerId","isMainnet","MAINNET","isTestnet","WEB_TESTNET","isPreviewnet","WEB_PREVIEWNET","nodeAccountId","accountIdObj","Object","entries","split"],"mappings":"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"}
|
|
@@ -227,7 +227,8 @@ class MirrorNodeContractQuery {
|
|
|
227
227
|
const host = mirrorNode.address.address;
|
|
228
228
|
const isLocalEnvironment = host === "localhost" || host === "127.0.0.1";
|
|
229
229
|
if (isLocalEnvironment) {
|
|
230
|
-
// For local environments, use HTTP scheme and port 8545
|
|
230
|
+
// For local environments, use HTTP scheme and port 8545 for contract calls
|
|
231
|
+
// (different from general mirror node REST API port 5551)
|
|
231
232
|
const url = new URL(mirrorRestApiBaseUrl);
|
|
232
233
|
url.protocol = "http:";
|
|
233
234
|
url.port = "8545";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MirrorNodeContractQuery.js","sources":["../../src/query/MirrorNodeContractQuery.js"],"sourcesContent":["import ContractFunctionParameters from \"../contract/ContractFunctionParameters.js\";\n\n/**\n * @typedef {import(\"../contract/ContractId\").default} ContractId\n * @typedef {import(\"../account/AccountId\").default} AccountId\n * @typedef {import(\"../client/Client.js\").default<*, *>} Client\n *\n */\n\n/**\n * @typedef {object} MirrorNodeResponse\n * @property {string} result\n * @property {string} [error]\n * @property {string} [gasUsed]\n * @property {string} [contractAddress]\n * @property {string} [status]\n */\n\n/**\n * MirrorNodeContractQuery returns a result from EVM execution such as cost-free execution of read-only smart contract\n * queries, gas estimation, and transient simulation of read-write operations.\n * When working with sender that has ECDSA key with alias, you MUST:\n * 1. Retrieve the account's EVM address from the Mirror Node API first\n * 2. Use setSenderEvmAddress() instead of setSender()\n *\n * This is because EVM addresses for accounts with ECDSA keys and aliases cannot be automatically\n * derived and must be fetched from the Mirror Node. Example:\n *\n * ```javascript\n * // For accounts with ECDSA keys and aliases:\n * const evmAddress = // ... fetch from Mirror Node API ...\n * query.setSenderEvmAddress(evmAddress);\n * ```\n */\nexport default class MirrorNodeContractQuery {\n constructor() {\n this._contractId = null;\n this._contractEvmAddress = null;\n this._sender = null;\n this._senderEvmAddress = null;\n this._functionName = null;\n this._functionParameters = null;\n this._value = null;\n this._gasLimit = null;\n this._gasPrice = null;\n this._blockNumber = null;\n }\n\n /**\n *\n * @param {ContractId} contractId\n * @description Sets the contract instance to call.\n * @returns {this}\n */\n setContractId(contractId) {\n this._contractId = contractId;\n return this;\n }\n\n /**\n * @param {AccountId} sender\n * @description Sets the sender of the transaction simulation.\n * @returns {this}\n */\n setSender(sender) {\n this._sender = sender;\n return this;\n }\n\n /**\n * @param {string} sender\n * @description Set the 20-byte EVM address of the sender.\n * This method must be used explicitly when working with accounts that have ECDSA keys with aliases,\n * as their EVM addresses cannot be automatically derived and must be retrieved from the Mirror Node API.\n * The EVM address can be filled using `accountId.populateAccountEvmAddress(client)`\n * @returns {this}\n */\n setSenderEvmAddress(sender) {\n this._senderEvmAddress = sender;\n return this;\n }\n\n /**\n *\n * @param {string} name\n * @param {ContractFunctionParameters} functionParameters\n * @description Sets the function to call, and the parameters to pass to the function\n * @returns {this}\n */\n setFunction(name, functionParameters) {\n this._functionParameters =\n functionParameters != null\n ? functionParameters._build(name)\n : new ContractFunctionParameters()._build(name);\n\n return this;\n }\n\n /**\n * @param {Long} value\n * @description Sets the amount of value (in tinybars or wei) to be sent to the contract in the transaction.\n * Use this to specify an amount for a payable function call.\n * @returns {this}\n */\n setValue(value) {\n this._value = value;\n return this;\n }\n\n /**\n * @param {Long} gasLimit\n * @description Sets the gas limit for the contract call.\n * This specifies the maximum amount of gas that the transaction can consume.\n * @returns {this}\n */\n setGasLimit(gasLimit) {\n this._gasLimit = gasLimit;\n return this;\n }\n\n /**\n * @param {Long} gasPrice\n * @description Sets the gas price to be used for the contract call. This specifies the price of each unit of gas used in the transaction.\n * @returns {this}\n */\n setGasPrice(gasPrice) {\n this._gasPrice = gasPrice;\n return this;\n }\n\n /**\n * @param {Long} blockNumber\n * @description Sets the block number for the simulation of the contract call.\n * The block number determines the context of the contract call simulation within the blockchain.\n * @returns {this}\n */\n setBlockNumber(blockNumber) {\n this._blockNumber = blockNumber;\n return this;\n }\n\n /**\n * @returns {ContractId?}\n */\n get contractId() {\n return this._contractId;\n }\n\n /**\n * @returns {string}\n */\n get contractEvmAddress() {\n const solidityAddress = this._contractId?.toEvmAddress();\n if (solidityAddress == null) {\n throw new Error(\"Contract ID is not set\");\n }\n return solidityAddress;\n }\n\n /**\n * @returns {AccountId?}\n */\n get sender() {\n return this._sender;\n }\n\n /**\n * @returns {string | null }\n */\n get senderEvmAddress() {\n return this._senderEvmAddress;\n }\n\n /**\n * @returns {Uint8Array | null | undefined}\n */\n get callData() {\n return this._functionParameters;\n }\n\n /**\n * @returns {Long?}\n */\n get value() {\n return this._value;\n }\n\n /**\n * @returns {Long?}\n */\n get gasLimit() {\n return this._gasLimit;\n }\n\n /**\n * @returns {Long?}\n */\n get gasPrice() {\n return this._gasPrice;\n }\n\n /**\n * @returns {Long?}\n */\n get blockNumber() {\n return this._blockNumber;\n }\n\n /**\n *\n * @param {Client} client\n * @param {object} jsonPayload\n * @returns {Promise<MirrorNodeResponse>}\n */\n async performMirrorNodeRequest(client, jsonPayload) {\n if (this.contractId == null) {\n throw new Error(\"Contract ID is not set\");\n }\n this._fillEvmAddress();\n let mirrorRestApiBaseUrl = client.mirrorRestApiBaseUrl;\n const contractCallEndpointPath = \"/contracts/call\";\n\n // Check if this is a local environment (localhost or 127.0.0.1)\n const mirrorNode = client._mirrorNetwork.getNextMirrorNode();\n const host = mirrorNode.address.address;\n const isLocalEnvironment = host === \"localhost\" || host === \"127.0.0.1\";\n\n if (isLocalEnvironment) {\n // For local environments, use HTTP scheme and port 8545\n const url = new URL(mirrorRestApiBaseUrl);\n url.protocol = \"http:\";\n url.port = \"8545\";\n mirrorRestApiBaseUrl = url.toString();\n }\n\n const contractCallEndpointUrl = `${mirrorRestApiBaseUrl}${contractCallEndpointPath}`;\n\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n const response = await fetch(contractCallEndpointUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(jsonPayload),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const data = /** @type {MirrorNodeResponse} */ (await response.json());\n return data;\n }\n\n _fillEvmAddress() {\n if (this.senderEvmAddress == null && this.sender != null) {\n this._senderEvmAddress = this.sender.toEvmAddress();\n }\n }\n // eslint-disable-next-line jsdoc/require-returns-check\n /**\n * @returns {object}\n */\n get JSONPayload() {\n throw new Error(\n \"JSONPayload getter is not implemented. Please implement this method in the subclass.\",\n );\n }\n}\n"],"names":["MirrorNodeContractQuery","constructor","this","_contractId","_contractEvmAddress","_sender","_senderEvmAddress","_functionName","_functionParameters","_value","_gasLimit","_gasPrice","_blockNumber","setContractId","contractId","setSender","sender","setSenderEvmAddress","setFunction","name","functionParameters","_build","ContractFunctionParameters","setValue","value","setGasLimit","gasLimit","setGasPrice","gasPrice","setBlockNumber","blockNumber","contractEvmAddress","solidityAddress","toEvmAddress","Error","senderEvmAddress","callData","performMirrorNodeRequest","client","jsonPayload","_fillEvmAddress","mirrorRestApiBaseUrl","host","_mirrorNetwork","getNextMirrorNode","address","url","URL","protocol","port","toString","contractCallEndpointUrl","response","fetch","method","headers","body","JSON","stringify","ok","status","json","JSONPayload"],"mappings":"yDAkCe,MAAMA,EACjB,WAAAC,GACIC,KAAKC,YAAc,KACnBD,KAAKE,oBAAsB,KAC3BF,KAAKG,QAAU,KACfH,KAAKI,kBAAoB,KACzBJ,KAAKK,cAAgB,KACrBL,KAAKM,oBAAsB,KAC3BN,KAAKO,OAAS,KACdP,KAAKQ,UAAY,KACjBR,KAAKS,UAAY,KACjBT,KAAKU,aAAe,IAC5B,CAQI,aAAAC,CAAcC,GAEV,OADAZ,KAAKC,YAAcW,EACZZ,IACf,CAOI,SAAAa,CAAUC,GAEN,OADAd,KAAKG,QAAUW,EACRd,IACf,CAUI,mBAAAe,CAAoBD,GAEhB,OADAd,KAAKI,kBAAoBU,EAClBd,IACf,CASI,WAAAgB,CAAYC,EAAMC,GAMd,OALAlB,KAAKM,oBACqB,MAAtBY,EACMA,EAAmBC,OAAOF,IAC1B,IAAIG,GAA6BD,OAAOF,GAE3CjB,IACf,CAQI,QAAAqB,CAASC,GAEL,OADAtB,KAAKO,OAASe,EACPtB,IACf,CAQI,WAAAuB,CAAYC,GAER,OADAxB,KAAKQ,UAAYgB,EACVxB,IACf,CAOI,WAAAyB,CAAYC,GAER,OADA1B,KAAKS,UAAYiB,EACV1B,IACf,CAQI,cAAA2B,CAAeC,GAEX,OADA5B,KAAKU,aAAekB,EACb5B,IACf,CAKI,cAAIY,GACA,OAAOZ,KAAKC,WACpB,CAKI,sBAAI4B,GACA,MAAMC,EAAkB9B,KAAKC,aAAa8B,eAC1C,GAAuB,MAAnBD,EACA,MAAM,IAAIE,MAAM,0BAEpB,OAAOF,CACf,CAKI,UAAIhB,GACA,OAAOd,KAAKG,OACpB,CAKI,oBAAI8B,GACA,OAAOjC,KAAKI,iBACpB,CAKI,YAAI8B,GACA,OAAOlC,KAAKM,mBACpB,CAKI,SAAIgB,GACA,OAAOtB,KAAKO,MACpB,CAKI,YAAIiB,GACA,OAAOxB,KAAKQ,SACpB,CAKI,YAAIkB,GACA,OAAO1B,KAAKS,SACpB,CAKI,eAAImB,GACA,OAAO5B,KAAKU,YACpB,CAQI,8BAAMyB,CAAyBC,EAAQC,GACnC,GAAuB,MAAnBrC,KAAKY,WACL,MAAM,IAAIoB,MAAM,0BAEpBhC,KAAKsC,kBACL,IAAIC,EAAuBH,EAAOG,qBAClC,MAIMC,EADaJ,EAAOK,eAAeC,oBACjBC,QAAQA,QAGhC,GAFoC,cAATH,GAAiC,cAATA,EAE3B,CAEpB,MAAMI,EAAM,IAAIC,IAAIN,GACpBK,EAAIE,SAAW,QACfF,EAAIG,KAAO,OACXR,EAAuBK,EAAII,UACvC,CAEQ,MAAMC,EAA0B,GAAGV,mBAG7BW,QAAiBC,MAAMF,EAAyB,CAClDG,OAAQ,OACRC,QAAS,CACL,eAAgB,oBAEpBC,KAAMC,KAAKC,UAAUnB,KAGzB,IAAKa,EAASO,GACV,MAAM,IAAIzB,MAAM,uBAAuBkB,EAASQ,UAKpD,aADsDR,EAASS,MAEvE,CAEI,eAAArB,GACiC,MAAzBtC,KAAKiC,kBAA2C,MAAfjC,KAAKc,SACtCd,KAAKI,kBAAoBJ,KAAKc,OAAOiB,eAEjD,CAKI,eAAI6B,GACA,MAAM,IAAI5B,MACN,uFAEZ"}
|
|
1
|
+
{"version":3,"file":"MirrorNodeContractQuery.js","sources":["../../src/query/MirrorNodeContractQuery.js"],"sourcesContent":["import ContractFunctionParameters from \"../contract/ContractFunctionParameters.js\";\n\n/**\n * @typedef {import(\"../contract/ContractId\").default} ContractId\n * @typedef {import(\"../account/AccountId\").default} AccountId\n * @typedef {import(\"../client/Client.js\").default<*, *>} Client\n *\n */\n\n/**\n * @typedef {object} MirrorNodeResponse\n * @property {string} result\n * @property {string} [error]\n * @property {string} [gasUsed]\n * @property {string} [contractAddress]\n * @property {string} [status]\n */\n\n/**\n * MirrorNodeContractQuery returns a result from EVM execution such as cost-free execution of read-only smart contract\n * queries, gas estimation, and transient simulation of read-write operations.\n * When working with sender that has ECDSA key with alias, you MUST:\n * 1. Retrieve the account's EVM address from the Mirror Node API first\n * 2. Use setSenderEvmAddress() instead of setSender()\n *\n * This is because EVM addresses for accounts with ECDSA keys and aliases cannot be automatically\n * derived and must be fetched from the Mirror Node. Example:\n *\n * ```javascript\n * // For accounts with ECDSA keys and aliases:\n * const evmAddress = // ... fetch from Mirror Node API ...\n * query.setSenderEvmAddress(evmAddress);\n * ```\n */\nexport default class MirrorNodeContractQuery {\n constructor() {\n this._contractId = null;\n this._contractEvmAddress = null;\n this._sender = null;\n this._senderEvmAddress = null;\n this._functionName = null;\n this._functionParameters = null;\n this._value = null;\n this._gasLimit = null;\n this._gasPrice = null;\n this._blockNumber = null;\n }\n\n /**\n *\n * @param {ContractId} contractId\n * @description Sets the contract instance to call.\n * @returns {this}\n */\n setContractId(contractId) {\n this._contractId = contractId;\n return this;\n }\n\n /**\n * @param {AccountId} sender\n * @description Sets the sender of the transaction simulation.\n * @returns {this}\n */\n setSender(sender) {\n this._sender = sender;\n return this;\n }\n\n /**\n * @param {string} sender\n * @description Set the 20-byte EVM address of the sender.\n * This method must be used explicitly when working with accounts that have ECDSA keys with aliases,\n * as their EVM addresses cannot be automatically derived and must be retrieved from the Mirror Node API.\n * The EVM address can be filled using `accountId.populateAccountEvmAddress(client)`\n * @returns {this}\n */\n setSenderEvmAddress(sender) {\n this._senderEvmAddress = sender;\n return this;\n }\n\n /**\n *\n * @param {string} name\n * @param {ContractFunctionParameters} functionParameters\n * @description Sets the function to call, and the parameters to pass to the function\n * @returns {this}\n */\n setFunction(name, functionParameters) {\n this._functionParameters =\n functionParameters != null\n ? functionParameters._build(name)\n : new ContractFunctionParameters()._build(name);\n\n return this;\n }\n\n /**\n * @param {Long} value\n * @description Sets the amount of value (in tinybars or wei) to be sent to the contract in the transaction.\n * Use this to specify an amount for a payable function call.\n * @returns {this}\n */\n setValue(value) {\n this._value = value;\n return this;\n }\n\n /**\n * @param {Long} gasLimit\n * @description Sets the gas limit for the contract call.\n * This specifies the maximum amount of gas that the transaction can consume.\n * @returns {this}\n */\n setGasLimit(gasLimit) {\n this._gasLimit = gasLimit;\n return this;\n }\n\n /**\n * @param {Long} gasPrice\n * @description Sets the gas price to be used for the contract call. This specifies the price of each unit of gas used in the transaction.\n * @returns {this}\n */\n setGasPrice(gasPrice) {\n this._gasPrice = gasPrice;\n return this;\n }\n\n /**\n * @param {Long} blockNumber\n * @description Sets the block number for the simulation of the contract call.\n * The block number determines the context of the contract call simulation within the blockchain.\n * @returns {this}\n */\n setBlockNumber(blockNumber) {\n this._blockNumber = blockNumber;\n return this;\n }\n\n /**\n * @returns {ContractId?}\n */\n get contractId() {\n return this._contractId;\n }\n\n /**\n * @returns {string}\n */\n get contractEvmAddress() {\n const solidityAddress = this._contractId?.toEvmAddress();\n if (solidityAddress == null) {\n throw new Error(\"Contract ID is not set\");\n }\n return solidityAddress;\n }\n\n /**\n * @returns {AccountId?}\n */\n get sender() {\n return this._sender;\n }\n\n /**\n * @returns {string | null }\n */\n get senderEvmAddress() {\n return this._senderEvmAddress;\n }\n\n /**\n * @returns {Uint8Array | null | undefined}\n */\n get callData() {\n return this._functionParameters;\n }\n\n /**\n * @returns {Long?}\n */\n get value() {\n return this._value;\n }\n\n /**\n * @returns {Long?}\n */\n get gasLimit() {\n return this._gasLimit;\n }\n\n /**\n * @returns {Long?}\n */\n get gasPrice() {\n return this._gasPrice;\n }\n\n /**\n * @returns {Long?}\n */\n get blockNumber() {\n return this._blockNumber;\n }\n\n /**\n *\n * @param {Client} client\n * @param {object} jsonPayload\n * @returns {Promise<MirrorNodeResponse>}\n */\n async performMirrorNodeRequest(client, jsonPayload) {\n if (this.contractId == null) {\n throw new Error(\"Contract ID is not set\");\n }\n this._fillEvmAddress();\n let mirrorRestApiBaseUrl = client.mirrorRestApiBaseUrl;\n const contractCallEndpointPath = \"/contracts/call\";\n\n // Check if this is a local environment (localhost or 127.0.0.1)\n const mirrorNode = client._mirrorNetwork.getNextMirrorNode();\n const host = mirrorNode.address.address;\n const isLocalEnvironment = host === \"localhost\" || host === \"127.0.0.1\";\n\n if (isLocalEnvironment) {\n // For local environments, use HTTP scheme and port 8545 for contract calls\n // (different from general mirror node REST API port 5551)\n const url = new URL(mirrorRestApiBaseUrl);\n url.protocol = \"http:\";\n url.port = \"8545\";\n mirrorRestApiBaseUrl = url.toString();\n }\n\n const contractCallEndpointUrl = `${mirrorRestApiBaseUrl}${contractCallEndpointPath}`;\n\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n const response = await fetch(contractCallEndpointUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(jsonPayload),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const data = /** @type {MirrorNodeResponse} */ (await response.json());\n return data;\n }\n\n _fillEvmAddress() {\n if (this.senderEvmAddress == null && this.sender != null) {\n this._senderEvmAddress = this.sender.toEvmAddress();\n }\n }\n // eslint-disable-next-line jsdoc/require-returns-check\n /**\n * @returns {object}\n */\n get JSONPayload() {\n throw new Error(\n \"JSONPayload getter is not implemented. Please implement this method in the subclass.\",\n );\n }\n}\n"],"names":["MirrorNodeContractQuery","constructor","this","_contractId","_contractEvmAddress","_sender","_senderEvmAddress","_functionName","_functionParameters","_value","_gasLimit","_gasPrice","_blockNumber","setContractId","contractId","setSender","sender","setSenderEvmAddress","setFunction","name","functionParameters","_build","ContractFunctionParameters","setValue","value","setGasLimit","gasLimit","setGasPrice","gasPrice","setBlockNumber","blockNumber","contractEvmAddress","solidityAddress","toEvmAddress","Error","senderEvmAddress","callData","performMirrorNodeRequest","client","jsonPayload","_fillEvmAddress","mirrorRestApiBaseUrl","host","_mirrorNetwork","getNextMirrorNode","address","url","URL","protocol","port","toString","contractCallEndpointUrl","response","fetch","method","headers","body","JSON","stringify","ok","status","json","JSONPayload"],"mappings":"yDAkCe,MAAMA,EACjB,WAAAC,GACIC,KAAKC,YAAc,KACnBD,KAAKE,oBAAsB,KAC3BF,KAAKG,QAAU,KACfH,KAAKI,kBAAoB,KACzBJ,KAAKK,cAAgB,KACrBL,KAAKM,oBAAsB,KAC3BN,KAAKO,OAAS,KACdP,KAAKQ,UAAY,KACjBR,KAAKS,UAAY,KACjBT,KAAKU,aAAe,IAC5B,CAQI,aAAAC,CAAcC,GAEV,OADAZ,KAAKC,YAAcW,EACZZ,IACf,CAOI,SAAAa,CAAUC,GAEN,OADAd,KAAKG,QAAUW,EACRd,IACf,CAUI,mBAAAe,CAAoBD,GAEhB,OADAd,KAAKI,kBAAoBU,EAClBd,IACf,CASI,WAAAgB,CAAYC,EAAMC,GAMd,OALAlB,KAAKM,oBACqB,MAAtBY,EACMA,EAAmBC,OAAOF,IAC1B,IAAIG,GAA6BD,OAAOF,GAE3CjB,IACf,CAQI,QAAAqB,CAASC,GAEL,OADAtB,KAAKO,OAASe,EACPtB,IACf,CAQI,WAAAuB,CAAYC,GAER,OADAxB,KAAKQ,UAAYgB,EACVxB,IACf,CAOI,WAAAyB,CAAYC,GAER,OADA1B,KAAKS,UAAYiB,EACV1B,IACf,CAQI,cAAA2B,CAAeC,GAEX,OADA5B,KAAKU,aAAekB,EACb5B,IACf,CAKI,cAAIY,GACA,OAAOZ,KAAKC,WACpB,CAKI,sBAAI4B,GACA,MAAMC,EAAkB9B,KAAKC,aAAa8B,eAC1C,GAAuB,MAAnBD,EACA,MAAM,IAAIE,MAAM,0BAEpB,OAAOF,CACf,CAKI,UAAIhB,GACA,OAAOd,KAAKG,OACpB,CAKI,oBAAI8B,GACA,OAAOjC,KAAKI,iBACpB,CAKI,YAAI8B,GACA,OAAOlC,KAAKM,mBACpB,CAKI,SAAIgB,GACA,OAAOtB,KAAKO,MACpB,CAKI,YAAIiB,GACA,OAAOxB,KAAKQ,SACpB,CAKI,YAAIkB,GACA,OAAO1B,KAAKS,SACpB,CAKI,eAAImB,GACA,OAAO5B,KAAKU,YACpB,CAQI,8BAAMyB,CAAyBC,EAAQC,GACnC,GAAuB,MAAnBrC,KAAKY,WACL,MAAM,IAAIoB,MAAM,0BAEpBhC,KAAKsC,kBACL,IAAIC,EAAuBH,EAAOG,qBAClC,MAIMC,EADaJ,EAAOK,eAAeC,oBACjBC,QAAQA,QAGhC,GAFoC,cAATH,GAAiC,cAATA,EAE3B,CAGpB,MAAMI,EAAM,IAAIC,IAAIN,GACpBK,EAAIE,SAAW,QACfF,EAAIG,KAAO,OACXR,EAAuBK,EAAII,UACvC,CAEQ,MAAMC,EAA0B,GAAGV,mBAG7BW,QAAiBC,MAAMF,EAAyB,CAClDG,OAAQ,OACRC,QAAS,CACL,eAAgB,oBAEpBC,KAAMC,KAAKC,UAAUnB,KAGzB,IAAKa,EAASO,GACV,MAAM,IAAIzB,MAAM,uBAAuBkB,EAASQ,UAKpD,aADsDR,EAASS,MAEvE,CAEI,eAAArB,GACiC,MAAzBtC,KAAKiC,kBAA2C,MAAfjC,KAAKc,SACtCd,KAAKI,kBAAoBJ,KAAKc,OAAOiB,eAEjD,CAKI,eAAI6B,GACA,MAAM,IAAI5B,MACN,uFAEZ"}
|
|
@@ -10,14 +10,18 @@ var _TokenId = _interopRequireDefault(require("./TokenId.cjs"));
|
|
|
10
10
|
var _NftId = _interopRequireDefault(require("./NftId.cjs"));
|
|
11
11
|
var _AccountId = _interopRequireDefault(require("../account/AccountId.cjs"));
|
|
12
12
|
var _Transaction = _interopRequireDefault(require("../transaction/Transaction.cjs"));
|
|
13
|
-
var _long = _interopRequireDefault(require("long"));
|
|
14
13
|
var _NullableTokenDecimalMap = _interopRequireDefault(require("../account/NullableTokenDecimalMap.cjs"));
|
|
15
14
|
var _TokenNftTransferMap = _interopRequireDefault(require("../account/TokenNftTransferMap.cjs"));
|
|
16
15
|
var _TokenTransferMap = _interopRequireDefault(require("../account/TokenTransferMap.cjs"));
|
|
17
16
|
var _TokenTransferAccountMap = _interopRequireDefault(require("../account/TokenTransferAccountMap.cjs"));
|
|
17
|
+
var _util = require("../util.cjs");
|
|
18
18
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
19
19
|
// SPDX-License-Identifier: Apache-2.0
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {import("bignumber.js").default} BigNumber
|
|
23
|
+
*/
|
|
24
|
+
|
|
21
25
|
/**
|
|
22
26
|
* @namespace proto
|
|
23
27
|
* @typedef {import("@hashgraph/proto").proto.ITokenAirdropTransactionBody} HieroProto.proto.ITokenAirdropTransactionBody
|
|
@@ -27,7 +31,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
27
31
|
* @typedef {object} TransferTokensInput
|
|
28
32
|
* @property {TokenId | string} tokenId
|
|
29
33
|
* @property {AccountId | string} accountId
|
|
30
|
-
* @property {Long | number} amount
|
|
34
|
+
* @property {Long | number | BigNumber | bigint} amount
|
|
31
35
|
*/
|
|
32
36
|
|
|
33
37
|
/**
|
|
@@ -80,7 +84,7 @@ class AbstractTokenTransferTransaction extends _Transaction.default {
|
|
|
80
84
|
/**
|
|
81
85
|
* @param {TokenId | string} tokenId
|
|
82
86
|
* @param {AccountId | string} accountId
|
|
83
|
-
* @param {number | Long} amount
|
|
87
|
+
* @param {number | Long | BigNumber | bigint} amount
|
|
84
88
|
* @param {boolean} isApproved
|
|
85
89
|
* @param {number | null} expectedDecimals
|
|
86
90
|
* @returns {this}
|
|
@@ -89,7 +93,7 @@ class AbstractTokenTransferTransaction extends _Transaction.default {
|
|
|
89
93
|
this._requireNotFrozen();
|
|
90
94
|
const token = tokenId instanceof _TokenId.default ? tokenId : _TokenId.default.fromString(tokenId);
|
|
91
95
|
const account = accountId instanceof _AccountId.default ? accountId : _AccountId.default.fromString(accountId);
|
|
92
|
-
const value =
|
|
96
|
+
const value = (0, _util.convertAmountToLong)(amount);
|
|
93
97
|
for (const tokenTransfer of this._tokenTransfers) {
|
|
94
98
|
if (tokenTransfer.tokenId.compare(token) === 0 && tokenTransfer.accountId.compare(account) === 0) {
|
|
95
99
|
tokenTransfer.amount = tokenTransfer.amount.add(value);
|
|
@@ -110,7 +114,7 @@ class AbstractTokenTransferTransaction extends _Transaction.default {
|
|
|
110
114
|
/**
|
|
111
115
|
* @param {TokenId | string} tokenId
|
|
112
116
|
* @param {AccountId | string} accountId
|
|
113
|
-
* @param {number | Long} amount
|
|
117
|
+
* @param {number | Long | BigNumber | bigint} amount
|
|
114
118
|
* @returns {this}
|
|
115
119
|
*/
|
|
116
120
|
addTokenTransfer(tokenId, accountId, amount) {
|
|
@@ -186,7 +190,7 @@ class AbstractTokenTransferTransaction extends _Transaction.default {
|
|
|
186
190
|
/**
|
|
187
191
|
* @param {TokenId | string} tokenId
|
|
188
192
|
* @param {AccountId | string} accountId
|
|
189
|
-
* @param {number | Long} amount
|
|
193
|
+
* @param {number | Long | BigNumber | bigint} amount
|
|
190
194
|
* @returns {this}
|
|
191
195
|
*/
|
|
192
196
|
addApprovedTokenTransfer(tokenId, accountId, amount) {
|
|
@@ -196,7 +200,7 @@ class AbstractTokenTransferTransaction extends _Transaction.default {
|
|
|
196
200
|
/**
|
|
197
201
|
* @param {TokenId | string} tokenId
|
|
198
202
|
* @param {AccountId | string} accountId
|
|
199
|
-
* @param {number | Long} amount
|
|
203
|
+
* @param {number | Long | BigNumber | bigint} amount
|
|
200
204
|
* @param {number} decimals
|
|
201
205
|
* @returns {this}
|
|
202
206
|
*/
|
|
@@ -204,7 +208,7 @@ class AbstractTokenTransferTransaction extends _Transaction.default {
|
|
|
204
208
|
this._requireNotFrozen();
|
|
205
209
|
const token = tokenId instanceof _TokenId.default ? tokenId : _TokenId.default.fromString(tokenId);
|
|
206
210
|
const account = accountId instanceof _AccountId.default ? accountId : _AccountId.default.fromString(accountId);
|
|
207
|
-
const value =
|
|
211
|
+
const value = (0, _util.convertAmountToLong)(amount);
|
|
208
212
|
let found = false;
|
|
209
213
|
for (const tokenTransfer of this._tokenTransfers) {
|
|
210
214
|
if (tokenTransfer.tokenId.compare(token) === 0) {
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import("bignumber.js").default} BigNumber
|
|
3
|
+
*/
|
|
1
4
|
/**
|
|
2
5
|
* @namespace proto
|
|
3
6
|
* @typedef {import("@hashgraph/proto").proto.ITokenAirdropTransactionBody} HieroProto.proto.ITokenAirdropTransactionBody
|
|
@@ -6,7 +9,7 @@
|
|
|
6
9
|
* @typedef {object} TransferTokensInput
|
|
7
10
|
* @property {TokenId | string} tokenId
|
|
8
11
|
* @property {AccountId | string} accountId
|
|
9
|
-
* @property {Long | number} amount
|
|
12
|
+
* @property {Long | number | BigNumber | bigint} amount
|
|
10
13
|
*/
|
|
11
14
|
/**
|
|
12
15
|
* @typedef {object} TransferNftInput
|
|
@@ -46,19 +49,19 @@ export default class AbstractTokenTransferTransaction extends Transaction {
|
|
|
46
49
|
/**
|
|
47
50
|
* @param {TokenId | string} tokenId
|
|
48
51
|
* @param {AccountId | string} accountId
|
|
49
|
-
* @param {number | Long} amount
|
|
52
|
+
* @param {number | Long | BigNumber | bigint} amount
|
|
50
53
|
* @param {boolean} isApproved
|
|
51
54
|
* @param {number | null} expectedDecimals
|
|
52
55
|
* @returns {this}
|
|
53
56
|
*/
|
|
54
|
-
_addTokenTransfer(tokenId: TokenId | string, accountId: AccountId | string, amount: number | Long, isApproved: boolean, expectedDecimals: number | null): this;
|
|
57
|
+
_addTokenTransfer(tokenId: TokenId | string, accountId: AccountId | string, amount: number | Long | BigNumber | bigint, isApproved: boolean, expectedDecimals: number | null): this;
|
|
55
58
|
/**
|
|
56
59
|
* @param {TokenId | string} tokenId
|
|
57
60
|
* @param {AccountId | string} accountId
|
|
58
|
-
* @param {number | Long} amount
|
|
61
|
+
* @param {number | Long | BigNumber | bigint} amount
|
|
59
62
|
* @returns {this}
|
|
60
63
|
*/
|
|
61
|
-
addTokenTransfer(tokenId: TokenId | string, accountId: AccountId | string, amount: number | Long): this;
|
|
64
|
+
addTokenTransfer(tokenId: TokenId | string, accountId: AccountId | string, amount: number | Long | BigNumber | bigint): this;
|
|
62
65
|
/**
|
|
63
66
|
* @param {boolean} isApproved
|
|
64
67
|
* @param {NftId | TokenId | string} tokenIdOrNftId
|
|
@@ -79,18 +82,18 @@ export default class AbstractTokenTransferTransaction extends Transaction {
|
|
|
79
82
|
/**
|
|
80
83
|
* @param {TokenId | string} tokenId
|
|
81
84
|
* @param {AccountId | string} accountId
|
|
82
|
-
* @param {number | Long} amount
|
|
85
|
+
* @param {number | Long | BigNumber | bigint} amount
|
|
83
86
|
* @returns {this}
|
|
84
87
|
*/
|
|
85
|
-
addApprovedTokenTransfer(tokenId: TokenId | string, accountId: AccountId | string, amount: number | Long): this;
|
|
88
|
+
addApprovedTokenTransfer(tokenId: TokenId | string, accountId: AccountId | string, amount: number | Long | BigNumber | bigint): this;
|
|
86
89
|
/**
|
|
87
90
|
* @param {TokenId | string} tokenId
|
|
88
91
|
* @param {AccountId | string} accountId
|
|
89
|
-
* @param {number | Long} amount
|
|
92
|
+
* @param {number | Long | BigNumber | bigint} amount
|
|
90
93
|
* @param {number} decimals
|
|
91
94
|
* @returns {this}
|
|
92
95
|
*/
|
|
93
|
-
addTokenTransferWithDecimals(tokenId: TokenId | string, accountId: AccountId | string, amount: number | Long, decimals: number): this;
|
|
96
|
+
addTokenTransferWithDecimals(tokenId: TokenId | string, accountId: AccountId | string, amount: number | Long | BigNumber | bigint, decimals: number): this;
|
|
94
97
|
/**
|
|
95
98
|
* @returns {NullableTokenDecimalMap}
|
|
96
99
|
*/
|
|
@@ -110,6 +113,7 @@ export default class AbstractTokenTransferTransaction extends Transaction {
|
|
|
110
113
|
*/
|
|
111
114
|
protected override _makeTransactionData(): HieroProto.proto.ITokenAirdropTransactionBody;
|
|
112
115
|
}
|
|
116
|
+
export type BigNumber = import("bignumber.js").default;
|
|
113
117
|
export namespace HieroProto {
|
|
114
118
|
namespace proto {
|
|
115
119
|
type ITokenAirdropTransactionBody = import("@hashgraph/proto").proto.ITokenAirdropTransactionBody;
|
|
@@ -118,7 +122,7 @@ export namespace HieroProto {
|
|
|
118
122
|
export type TransferTokensInput = {
|
|
119
123
|
tokenId: TokenId | string;
|
|
120
124
|
accountId: AccountId | string;
|
|
121
|
-
amount: Long | number;
|
|
125
|
+
amount: Long | number | BigNumber | bigint;
|
|
122
126
|
};
|
|
123
127
|
export type TransferNftInput = {
|
|
124
128
|
tokenId: TokenId | string;
|
|
@@ -132,7 +136,6 @@ import TokenNftTransfer from "../token/TokenNftTransfer.js";
|
|
|
132
136
|
import NftId from "./NftId.js";
|
|
133
137
|
import TokenId from "./TokenId.js";
|
|
134
138
|
import AccountId from "../account/AccountId.js";
|
|
135
|
-
import Long from "long";
|
|
136
139
|
import NullableTokenDecimalMap from "../account/NullableTokenDecimalMap.js";
|
|
137
140
|
import TokenNftTransferMap from "../account/TokenNftTransferMap.js";
|
|
138
141
|
import TokenTransferMap from "../account/TokenTransferMap.js";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"./TokenTransfer.js";import n from"./TokenNftTransfer.js";import t from"./TokenId.js";import r from"./NftId.js";import s from"../account/AccountId.js";import o from"../transaction/Transaction.js";import a from"
|
|
1
|
+
import e from"./TokenTransfer.js";import n from"./TokenNftTransfer.js";import t from"./TokenId.js";import r from"./NftId.js";import s from"../account/AccountId.js";import o from"../transaction/Transaction.js";import a from"../account/NullableTokenDecimalMap.js";import f from"../account/TokenNftTransferMap.js";import c from"../account/TokenTransferMap.js";import i from"../account/TokenTransferAccountMap.js";import{convertAmountToLong as d}from"../util.js";class u extends o{constructor(e={}){super(),this._tokenTransfers=[],this._nftTransfers=[];for(const n of null!=e.tokenTransfers?e.tokenTransfers:[])this.addTokenTransfer(n.tokenId,n.accountId,n.amount);for(const n of null!=e.nftTransfers?e.nftTransfers:[])this.addNftTransfer(n.tokenId,n.serial,n.sender,n.recipient)}addNftTransfer(e,n,t,r){return this._addNftTransfer(!1,e,n,t,r)}_addTokenTransfer(n,r,o,a,f){this._requireNotFrozen();const c=n instanceof t?n:t.fromString(n),i=r instanceof s?r:s.fromString(r),u=d(o);for(const e of this._tokenTransfers)if(0===e.tokenId.compare(c)&&0===e.accountId.compare(i))return e.amount=e.amount.add(u),e.expectedDecimals=f,this;return this._tokenTransfers.push(new e({tokenId:n,accountId:r,expectedDecimals:f,amount:o,isApproved:a})),this}addTokenTransfer(e,n,t){return this._addTokenTransfer(e,n,t,!1,null)}_addNftTransfer(e,o,a,f,c){let i,d,u;if(this._requireNotFrozen(),o instanceof r)i=o,d="string"==typeof a?s.fromString(a):a,u="string"==typeof f?s.fromString(f):f;else if(o instanceof t)i=new r(o,a),d="string"==typeof f?s.fromString(f):f,u="string"==typeof c?s.fromString(c):c;else try{i=r.fromString(o),d="string"==typeof a?s.fromString(a):a,u="string"==typeof f?s.fromString(f):f}catch(e){const n=t.fromString(o);i=new r(n,a),d="string"==typeof f?s.fromString(f):f,u="string"==typeof c?s.fromString(c):c}for(const e of this._nftTransfers)if(0===e.tokenId.compare(i.tokenId)&&0===e.serialNumber.compare(i.serial))return e.senderAccountId=d,e.receiverAccountId=u,this;return this._nftTransfers.push(new n({tokenId:i.tokenId,serialNumber:i.serial,senderAccountId:d,receiverAccountId:u,isApproved:e})),this}addApprovedNftTransfer(e,n,t,r){return this._addNftTransfer(!0,e,n,t,r)}addApprovedTokenTransfer(e,n,t){return this._addTokenTransfer(e,n,t,!0,null)}addTokenTransferWithDecimals(n,r,o,a){this._requireNotFrozen();const f=n instanceof t?n:t.fromString(n),c=r instanceof s?r:s.fromString(r),i=d(o);let u=!1;for(const e of this._tokenTransfers)if(0===e.tokenId.compare(f)){if(null!=e.expectedDecimals&&e.expectedDecimals!==a)throw new Error("expected decimals mis-match");e.expectedDecimals=a,0===e.accountId.compare(c)&&(e.amount=e.amount.add(i),e.expectedDecimals=a,u=!0)}return u||this._tokenTransfers.push(new e({tokenId:n,accountId:r,expectedDecimals:a,amount:o,isApproved:!1})),this}get tokenIdDecimals(){const e=new a;for(const n of this._tokenTransfers)e._set(n.tokenId,n.expectedDecimals);return e}get nftTransfers(){const e=new f;for(const n of this._nftTransfers){const t=e.get(n.tokenId),r={sender:n.senderAccountId,recipient:n.receiverAccountId,serial:n.serialNumber,isApproved:n.isApproved};null!=t?t.push(r):e._set(n.tokenId,[r])}return e}get tokenTransfers(){const e=new c;for(const n of this._tokenTransfers){let t=e.get(n.tokenId);null!=t?t._set(n.accountId,n.amount):(t=new i,t._set(n.accountId,n.amount),e._set(n.tokenId,t))}return e}_makeTransactionData(){const e=[];this._tokenTransfers.sort((e,n)=>{const t=e.tokenId.compare(n.tokenId);return 0!==t?t:e.accountId.compare(n.accountId)}),this._nftTransfers.sort((e,n)=>{const t=e.senderAccountId.compare(n.senderAccountId);if(0!=t)return t;const r=e.receiverAccountId.compare(n.receiverAccountId);return 0!=r?r:e.serialNumber.compare(n.serialNumber)});let n=0,t=0;for(;n<this._tokenTransfers.length||t<this._nftTransfers.length;)if(n<this._tokenTransfers.length&&t<this._nftTransfers.length){const r=this._tokenTransfers[n].tokenId,s=this._nftTransfers[t].tokenId,o=e.length>0?e[e.length-1]:null,a=null!=o?o.tokenId:null;if(null!=o&&null!=a&&0===a.compare(r)){o.transfers.push(this._tokenTransfers[n++]);continue}if(null!=o&&null!=a&&0===a.compare(s)){o.nftTransfers.push(this._nftTransfers[t++]);continue}const f=r.compare(s);0===f?e.push({tokenId:r,expectedDecimals:this._tokenTransfers[n].expectedDecimals,transfers:[this._tokenTransfers[n++]],nftTransfers:[this._nftTransfers[t++]]}):f<0?e.push({tokenId:r,expectedDecimals:this._tokenTransfers[n].expectedDecimals,transfers:[this._tokenTransfers[n++]],nftTransfers:[]}):e.push({tokenId:s,expectedDecimals:null,transfers:[],nftTransfers:[this._nftTransfers[t++]]})}else if(n<this._tokenTransfers.length){const t=this._tokenTransfers[n].tokenId;let r;for(const n of e)0===n.tokenId.compare(t)&&(r=n);const s=null!=r?r.tokenId:null;if(null!=r&&null!=s&&0===s.compare(t)){r.transfers.push(this._tokenTransfers[n++]);continue}e.push({tokenId:t,expectedDecimals:this._tokenTransfers[n].expectedDecimals,transfers:[this._tokenTransfers[n++]],nftTransfers:[]})}else if(t<this._nftTransfers.length){const n=this._nftTransfers[t].tokenId;let r;for(const t of e)0===t.tokenId.compare(n)&&(r=t);const s=null!=r?r.tokenId:null;if(null!=r&&null!=s&&0===s.compare(n)){r.nftTransfers.push(this._nftTransfers[t++]);continue}e.push({tokenId:n,expectedDecimals:null,transfers:[],nftTransfers:[this._nftTransfers[t++]]})}return{tokenTransfers:e.map(e=>({token:e.tokenId._toProtobuf(),expectedDecimals:null!=e.expectedDecimals?{value:e.expectedDecimals}:null,transfers:e.transfers.map(e=>e._toProtobuf()),nftTransfers:e.nftTransfers.map(e=>e._toProtobuf())}))}}}export{u as default};
|
|
2
2
|
//# sourceMappingURL=AbstractTokenTransferTransaction.js.map
|