@hiero-ledger/sdk 2.75.0 → 2.77.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 +440 -71
- package/dist/umd.min.js +14 -14
- package/lib/Executable.cjs +13 -3
- package/lib/Executable.js +1 -1
- package/lib/Executable.js.map +1 -1
- package/lib/channel/Channel.cjs +25 -1
- package/lib/channel/Channel.d.ts +20 -0
- package/lib/channel/Channel.js +1 -1
- package/lib/channel/Channel.js.map +1 -1
- package/lib/channel/NativeChannel.cjs +96 -2
- package/lib/channel/NativeChannel.d.ts +21 -1
- package/lib/channel/NativeChannel.js +1 -1
- package/lib/channel/NativeChannel.js.map +1 -1
- package/lib/channel/NodeChannel.cjs +4 -5
- package/lib/channel/NodeChannel.d.ts +2 -3
- package/lib/channel/NodeChannel.js +1 -1
- package/lib/channel/NodeChannel.js.map +1 -1
- package/lib/channel/WebChannel.cjs +163 -4
- package/lib/channel/WebChannel.d.ts +51 -1
- package/lib/channel/WebChannel.js +1 -1
- package/lib/channel/WebChannel.js.map +1 -1
- package/lib/client/Client.cjs +62 -5
- package/lib/client/Client.d.ts +26 -3
- package/lib/client/Client.js +1 -1
- package/lib/client/Client.js.map +1 -1
- package/lib/client/NativeClient.cjs +1 -1
- package/lib/client/NativeClient.js +1 -1
- package/lib/client/NativeClient.js.map +1 -1
- package/lib/client/NodeClient.cjs +7 -6
- package/lib/client/NodeClient.d.ts +3 -3
- package/lib/client/NodeClient.js +1 -1
- package/lib/client/NodeClient.js.map +1 -1
- package/lib/client/WebClient.cjs +61 -27
- package/lib/client/WebClient.d.ts +6 -0
- package/lib/client/WebClient.js +1 -1
- package/lib/client/WebClient.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 +18 -2
- package/lib/constants/ClientConstants.d.ts +15 -0
- package/lib/constants/ClientConstants.js +1 -1
- package/lib/constants/ClientConstants.js.map +1 -1
- package/lib/network/AddressBookQuery.cjs +0 -4
- package/lib/network/AddressBookQuery.js +1 -1
- package/lib/network/AddressBookQuery.js.map +1 -1
- package/lib/network/AddressBookQueryWeb.cjs +1 -5
- package/lib/network/AddressBookQueryWeb.js +1 -1
- package/lib/network/AddressBookQueryWeb.js.map +1 -1
- package/lib/version.js +1 -1
- package/package.json +9 -9
- package/src/Executable.js +18 -2
- package/src/channel/Channel.js +25 -1
- package/src/channel/NativeChannel.js +111 -2
- package/src/channel/NodeChannel.js +4 -7
- package/src/channel/WebChannel.js +189 -9
- package/src/client/Client.js +79 -5
- package/src/client/NativeClient.js +1 -1
- package/src/client/NodeClient.js +7 -6
- package/src/client/WebClient.js +77 -31
- 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 +17 -1
- package/src/network/AddressBookQuery.js +0 -7
- package/src/network/AddressBookQueryWeb.js +1 -8
|
@@ -10,15 +10,185 @@ import Channel, { encodeRequest, decodeUnaryResponse } from "./Channel.js";
|
|
|
10
10
|
export default class WebChannel extends Channel {
|
|
11
11
|
/**
|
|
12
12
|
* @param {string} address
|
|
13
|
+
* @param {number=} grpcDeadline
|
|
13
14
|
*/
|
|
14
|
-
constructor(address) {
|
|
15
|
-
super();
|
|
15
|
+
constructor(address, grpcDeadline) {
|
|
16
|
+
super(grpcDeadline);
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* @type {string}
|
|
19
20
|
* @private
|
|
20
21
|
*/
|
|
21
22
|
this._address = address;
|
|
23
|
+
|
|
24
|
+
// Set the gRPC deadline using the base class method
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Flag indicating if the connection is ready (health check has passed)
|
|
28
|
+
* Set to true after the first successful health check
|
|
29
|
+
*
|
|
30
|
+
* @type {boolean}
|
|
31
|
+
* @private
|
|
32
|
+
*/
|
|
33
|
+
this._isReady = false;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Promise that resolves when the health check is complete
|
|
37
|
+
* Used to prevent multiple concurrent health checks
|
|
38
|
+
*
|
|
39
|
+
* @type {Promise<void>|null}
|
|
40
|
+
* @private
|
|
41
|
+
*/
|
|
42
|
+
this._healthCheckPromise = null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Determines whether to use HTTPS based on the address
|
|
47
|
+
* @param {string} address - The address to check
|
|
48
|
+
* @returns {boolean} - True if HTTPS should be used, false for HTTP
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
_shouldUseHttps(address) {
|
|
52
|
+
return !(
|
|
53
|
+
address.includes("localhost") || address.includes("127.0.0.1")
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Builds the full URL with appropriate scheme (http/https)
|
|
59
|
+
* @param {string} address - The base address
|
|
60
|
+
* @returns {string} - The full URL with scheme
|
|
61
|
+
* @private
|
|
62
|
+
*/
|
|
63
|
+
_buildUrl(address) {
|
|
64
|
+
// Check if address already contains a scheme
|
|
65
|
+
const hasScheme =
|
|
66
|
+
address.startsWith("http://") || address.startsWith("https://");
|
|
67
|
+
|
|
68
|
+
if (hasScheme) {
|
|
69
|
+
// Use the address as-is if it already has a scheme
|
|
70
|
+
return address;
|
|
71
|
+
} else {
|
|
72
|
+
// Only prepend scheme if none exists
|
|
73
|
+
const shouldUseHttps = this._shouldUseHttps(address);
|
|
74
|
+
return shouldUseHttps ? `https://${address}` : `http://${address}`;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Check if the gRPC-Web proxy is reachable and healthy
|
|
80
|
+
* Performs a POST request and verifies the response has gRPC-Web headers,
|
|
81
|
+
* which indicates the proxy is running and processing gRPC requests.
|
|
82
|
+
* Results are cached per address for the entire lifecycle.
|
|
83
|
+
* Uses promise-based synchronization to prevent multiple concurrent health checks.
|
|
84
|
+
*
|
|
85
|
+
* @param {Date} deadline - Deadline for the health check
|
|
86
|
+
* @returns {Promise<void>}
|
|
87
|
+
* @private
|
|
88
|
+
*/
|
|
89
|
+
async _waitForReady(deadline) {
|
|
90
|
+
// Check if we've already validated this address
|
|
91
|
+
if (this._isReady) {
|
|
92
|
+
return; // Health check already passed for this address
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// If a health check is already in progress, wait for it to complete
|
|
96
|
+
if (this._healthCheckPromise) {
|
|
97
|
+
return this._healthCheckPromise;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Start a new health check and store the promise
|
|
101
|
+
this._healthCheckPromise = this._performHealthCheck(deadline);
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
await this._healthCheckPromise;
|
|
105
|
+
} finally {
|
|
106
|
+
// Clear the promise when done (success or failure)
|
|
107
|
+
this._healthCheckPromise = null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Performs the actual health check request
|
|
113
|
+
* @param {Date} deadline - Deadline for the health check
|
|
114
|
+
* @returns {Promise<void>}
|
|
115
|
+
* @private
|
|
116
|
+
*/
|
|
117
|
+
async _performHealthCheck(deadline) {
|
|
118
|
+
const address = this._buildUrl(this._address);
|
|
119
|
+
|
|
120
|
+
// Calculate remaining time until deadline
|
|
121
|
+
const timeoutMs = deadline.getTime() - Date.now();
|
|
122
|
+
if (timeoutMs <= 0) {
|
|
123
|
+
throw new GrpcServiceError(
|
|
124
|
+
GrpcStatus.Timeout,
|
|
125
|
+
ALL_WEB_NETWORK_NODES?.[this._address]?.toString(),
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const abortController = new AbortController();
|
|
130
|
+
const timeoutId = setTimeout(() => abortController.abort(), timeoutMs);
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
// Make a POST request to verify the gRPC-Web proxy is running
|
|
134
|
+
// We use a minimal gRPC-Web compatible request
|
|
135
|
+
//eslint-disable-next-line n/no-unsupported-features/node-builtins
|
|
136
|
+
const response = await fetch(address, {
|
|
137
|
+
method: "POST",
|
|
138
|
+
headers: {
|
|
139
|
+
"content-type": "application/grpc-web+proto",
|
|
140
|
+
"x-user-agent": `${SDK_NAME}/${SDK_VERSION}`,
|
|
141
|
+
"x-grpc-web": "1",
|
|
142
|
+
},
|
|
143
|
+
body: new Uint8Array(0), // Empty body for health check
|
|
144
|
+
signal: abortController.signal,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
clearTimeout(timeoutId);
|
|
148
|
+
|
|
149
|
+
// Check if response is successful (200) or indicates a redirect (3xx)
|
|
150
|
+
// 3xx status codes indicate the resource has moved, which is valid for proxies
|
|
151
|
+
if (
|
|
152
|
+
response.ok ||
|
|
153
|
+
(response.status >= 300 && response.status < 400)
|
|
154
|
+
) {
|
|
155
|
+
const grpcStatus = response.headers.get("grpc-status");
|
|
156
|
+
const grpcMessage = response.headers.get("grpc-message");
|
|
157
|
+
|
|
158
|
+
// If gRPC headers exist, the proxy is running and processing requests
|
|
159
|
+
if (grpcStatus != null || grpcMessage != null) {
|
|
160
|
+
// Mark this connection as ready
|
|
161
|
+
this._isReady = true;
|
|
162
|
+
return; // Healthy - gRPC-Web proxy is responding
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// If we get here, either status isn't 200/3xx or no gRPC headers present
|
|
167
|
+
// This means the proxy might not be configured correctly or not running
|
|
168
|
+
throw new GrpcServiceError(
|
|
169
|
+
GrpcStatus.Unavailable,
|
|
170
|
+
ALL_WEB_NETWORK_NODES?.[this._address]?.toString(),
|
|
171
|
+
);
|
|
172
|
+
} catch (error) {
|
|
173
|
+
clearTimeout(timeoutId);
|
|
174
|
+
|
|
175
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
176
|
+
throw new GrpcServiceError(
|
|
177
|
+
GrpcStatus.Timeout,
|
|
178
|
+
ALL_WEB_NETWORK_NODES?.[this._address]?.toString(),
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (error instanceof GrpcServiceError) {
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Network error - server is not reachable
|
|
187
|
+
throw new GrpcServiceError(
|
|
188
|
+
GrpcStatus.Unavailable,
|
|
189
|
+
ALL_WEB_NETWORK_NODES?.[this._address]?.toString(),
|
|
190
|
+
);
|
|
191
|
+
}
|
|
22
192
|
}
|
|
23
193
|
|
|
24
194
|
/**
|
|
@@ -38,15 +208,18 @@ export default class WebChannel extends Channel {
|
|
|
38
208
|
_createUnaryClient(serviceName) {
|
|
39
209
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
40
210
|
return async (method, requestData, callback) => {
|
|
211
|
+
// Calculate deadline for connection check
|
|
212
|
+
const deadline = new Date();
|
|
213
|
+
const milliseconds = this._grpcDeadline;
|
|
214
|
+
|
|
215
|
+
deadline.setMilliseconds(deadline.getMilliseconds() + milliseconds);
|
|
216
|
+
|
|
41
217
|
try {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
this._address.includes("127.0.0.1")
|
|
45
|
-
);
|
|
218
|
+
// Wait for connection to be ready (similar to gRPC waitForReady)
|
|
219
|
+
await this._waitForReady(deadline);
|
|
46
220
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
: `http://${this._address}`;
|
|
221
|
+
// Build the full URL with appropriate scheme
|
|
222
|
+
const address = this._buildUrl(this._address);
|
|
50
223
|
// this will be executed in a browser environment so eslint is
|
|
51
224
|
// disabled for the fetch call
|
|
52
225
|
//eslint-disable-next-line n/no-unsupported-features/node-builtins
|
|
@@ -68,6 +241,7 @@ export default class WebChannel extends Channel {
|
|
|
68
241
|
HttpStatus._fromValue(response.status),
|
|
69
242
|
);
|
|
70
243
|
callback(error, null);
|
|
244
|
+
return;
|
|
71
245
|
}
|
|
72
246
|
|
|
73
247
|
// Check headers for gRPC errors
|
|
@@ -81,6 +255,7 @@ export default class WebChannel extends Channel {
|
|
|
81
255
|
);
|
|
82
256
|
error.message = grpcMessage;
|
|
83
257
|
callback(error, null);
|
|
258
|
+
return;
|
|
84
259
|
}
|
|
85
260
|
|
|
86
261
|
const responseBuffer = await response.arrayBuffer();
|
|
@@ -88,6 +263,11 @@ export default class WebChannel extends Channel {
|
|
|
88
263
|
|
|
89
264
|
callback(null, unaryResponse);
|
|
90
265
|
} catch (error) {
|
|
266
|
+
if (error instanceof GrpcServiceError) {
|
|
267
|
+
callback(error, null);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
|
|
91
271
|
const err = new GrpcServiceError(
|
|
92
272
|
// retry on grpc web errors
|
|
93
273
|
GrpcStatus._fromValue(18),
|
package/src/client/Client.js
CHANGED
|
@@ -12,6 +12,10 @@ import FileId from "../file/FileId.js";
|
|
|
12
12
|
import Logger from "../logger/Logger.js"; // eslint-disable-line
|
|
13
13
|
import { convertToNumber } from "../util.js";
|
|
14
14
|
import AddressBookQuery from "../network/AddressBookQuery.js";
|
|
15
|
+
import {
|
|
16
|
+
DEFAULT_GRPC_DEADLINE,
|
|
17
|
+
DEFAULT_REQUEST_TIMEOUT,
|
|
18
|
+
} from "../constants/ClientConstants.js";
|
|
15
19
|
|
|
16
20
|
/**
|
|
17
21
|
* @typedef {import("../channel/Channel.js").default} Channel
|
|
@@ -40,6 +44,8 @@ import AddressBookQuery from "../network/AddressBookQuery.js";
|
|
|
40
44
|
* @property {boolean} [scheduleNetworkUpdate]
|
|
41
45
|
* @property {number} [shard]
|
|
42
46
|
* @property {number} [realm]
|
|
47
|
+
* @property {number} [grpcDeadline]
|
|
48
|
+
* @property {number} [requestTimeout]
|
|
43
49
|
*/
|
|
44
50
|
|
|
45
51
|
/**
|
|
@@ -127,7 +133,10 @@ export default class Client {
|
|
|
127
133
|
this._defaultRegenerateTransactionId = true;
|
|
128
134
|
|
|
129
135
|
/** @private */
|
|
130
|
-
this._requestTimeout =
|
|
136
|
+
this._requestTimeout = DEFAULT_REQUEST_TIMEOUT;
|
|
137
|
+
|
|
138
|
+
/** @private */
|
|
139
|
+
this._grpcDeadline = DEFAULT_GRPC_DEADLINE;
|
|
131
140
|
|
|
132
141
|
/**
|
|
133
142
|
* @type {boolean}
|
|
@@ -156,6 +165,23 @@ export default class Client {
|
|
|
156
165
|
this._realm = props.realm;
|
|
157
166
|
}
|
|
158
167
|
|
|
168
|
+
if (props != null && props.grpcDeadline != null) {
|
|
169
|
+
this.setGrpcDeadline(props.grpcDeadline);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (props != null && props.requestTimeout != null) {
|
|
173
|
+
this.setRequestTimeout(props.requestTimeout);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Validate that requestTimeout is larger than grpcDeadline after both are set
|
|
177
|
+
if (this._requestTimeout <= this._grpcDeadline) {
|
|
178
|
+
console.warn(
|
|
179
|
+
`DEPRECATION WARNING: requestTimeout (${this._requestTimeout}ms) should be larger than grpcDeadline (${this._grpcDeadline}ms). ` +
|
|
180
|
+
`This configuration may cause operations to fail unexpectedly. ` +
|
|
181
|
+
`This will throw an error in the next major version. Please adjust your timeout values.`,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
159
185
|
/** @internal */
|
|
160
186
|
/** @type {NodeJS.Timeout} */
|
|
161
187
|
this._timer;
|
|
@@ -675,21 +701,65 @@ export default class Client {
|
|
|
675
701
|
}
|
|
676
702
|
|
|
677
703
|
/**
|
|
678
|
-
*
|
|
704
|
+
* Set the total request timeout for complete operations.
|
|
705
|
+
*
|
|
706
|
+
* @param {number} requestTimeout - Maximum time in milliseconds for complete Transaction/Query operations
|
|
679
707
|
* @returns {this}
|
|
680
708
|
*/
|
|
681
709
|
setRequestTimeout(requestTimeout) {
|
|
710
|
+
if (requestTimeout <= 0) {
|
|
711
|
+
throw new Error("requestTimeout must be a positive number");
|
|
712
|
+
}
|
|
713
|
+
if (requestTimeout <= this._grpcDeadline) {
|
|
714
|
+
console.warn(
|
|
715
|
+
`DEPRECATION WARNING: requestTimeout (${requestTimeout}ms) should be larger than grpcDeadline (${this._grpcDeadline}ms). ` +
|
|
716
|
+
`This configuration may cause operations to fail unexpectedly. ` +
|
|
717
|
+
`This will throw an error in the next major version. Please adjust your timeout values.`,
|
|
718
|
+
);
|
|
719
|
+
}
|
|
682
720
|
this._requestTimeout = requestTimeout;
|
|
683
721
|
return this;
|
|
684
722
|
}
|
|
685
723
|
|
|
686
724
|
/**
|
|
687
|
-
*
|
|
725
|
+
* Get the total request timeout for complete operations.
|
|
726
|
+
*
|
|
727
|
+
* @returns {number} Maximum time in milliseconds for complete Transaction/Query operations
|
|
688
728
|
*/
|
|
689
729
|
get requestTimeout() {
|
|
690
730
|
return this._requestTimeout;
|
|
691
731
|
}
|
|
692
732
|
|
|
733
|
+
/**
|
|
734
|
+
* Set the global gRPC deadline for all requests.
|
|
735
|
+
*
|
|
736
|
+
* @param {number} grpcDeadline - Maximum time in milliseconds for a single gRPC request
|
|
737
|
+
* @returns {this}
|
|
738
|
+
*/
|
|
739
|
+
setGrpcDeadline(grpcDeadline) {
|
|
740
|
+
if (grpcDeadline <= 0) {
|
|
741
|
+
throw new Error("grpcDeadline must be a positive number");
|
|
742
|
+
}
|
|
743
|
+
if (grpcDeadline >= this._requestTimeout) {
|
|
744
|
+
console.warn(
|
|
745
|
+
`DEPRECATION WARNING: grpcDeadline (${grpcDeadline}ms) should be smaller than requestTimeout (${this._requestTimeout}ms). ` +
|
|
746
|
+
`This configuration may cause operations to fail unexpectedly. ` +
|
|
747
|
+
`This will throw an error in the next major version. Please adjust your timeout values.`,
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
this._grpcDeadline = grpcDeadline;
|
|
751
|
+
return this;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Get the global gRPC deadline for all requests.
|
|
756
|
+
*
|
|
757
|
+
* @returns {number} Maximum time in milliseconds for a single gRPC request
|
|
758
|
+
*/
|
|
759
|
+
get grpcDeadline() {
|
|
760
|
+
return this._grpcDeadline;
|
|
761
|
+
}
|
|
762
|
+
|
|
693
763
|
/**
|
|
694
764
|
* @returns {number}
|
|
695
765
|
*/
|
|
@@ -794,7 +864,9 @@ export default class Client {
|
|
|
794
864
|
* @returns {(address: string) => ChannelT}
|
|
795
865
|
*/
|
|
796
866
|
_createNetworkChannel() {
|
|
797
|
-
|
|
867
|
+
return () => {
|
|
868
|
+
throw new Error("not implemented");
|
|
869
|
+
};
|
|
798
870
|
}
|
|
799
871
|
|
|
800
872
|
/**
|
|
@@ -802,7 +874,9 @@ export default class Client {
|
|
|
802
874
|
* @returns {(address: string) => MirrorChannelT}
|
|
803
875
|
*/
|
|
804
876
|
_createMirrorNetworkChannel() {
|
|
805
|
-
|
|
877
|
+
return () => {
|
|
878
|
+
throw new Error("not implemented");
|
|
879
|
+
};
|
|
806
880
|
}
|
|
807
881
|
|
|
808
882
|
/**
|
|
@@ -307,7 +307,7 @@ export default class NativeClient extends Client {
|
|
|
307
307
|
* @returns {(address: string) => NativeChannel}
|
|
308
308
|
*/
|
|
309
309
|
_createNetworkChannel() {
|
|
310
|
-
return (address) => new NativeChannel(address);
|
|
310
|
+
return (address) => new NativeChannel(address, this.grpcDeadline);
|
|
311
311
|
}
|
|
312
312
|
|
|
313
313
|
/**
|
package/src/client/NodeClient.js
CHANGED
|
@@ -35,9 +35,6 @@ export default class NodeClient extends Client {
|
|
|
35
35
|
constructor(props) {
|
|
36
36
|
super(props);
|
|
37
37
|
|
|
38
|
-
/** @private */
|
|
39
|
-
this._maxExecutionTime = 10000;
|
|
40
|
-
|
|
41
38
|
if (props != null) {
|
|
42
39
|
if (typeof props.network === "string") {
|
|
43
40
|
this._setNetworkFromName(props.network);
|
|
@@ -267,12 +264,16 @@ export default class NodeClient extends Client {
|
|
|
267
264
|
|
|
268
265
|
/**
|
|
269
266
|
* Available only for NodeClient
|
|
270
|
-
*
|
|
267
|
+
* Legacy method maintained for backward compatibility.
|
|
268
|
+
* This method now calls setGrpcDeadline internally to ensure proper validation.
|
|
269
|
+
* @deprecated Use setGrpcDeadline instead.
|
|
271
270
|
* @param {number} maxExecutionTime
|
|
272
271
|
* @returns {this}
|
|
273
272
|
*/
|
|
274
273
|
setMaxExecutionTime(maxExecutionTime) {
|
|
275
|
-
|
|
274
|
+
// Use the parent class setGrpcDeadline method to ensure proper validation
|
|
275
|
+
// This ensures that maxExecutionTime follows the same validation rules as grpcDeadline
|
|
276
|
+
this.setGrpcDeadline(maxExecutionTime);
|
|
276
277
|
return this;
|
|
277
278
|
}
|
|
278
279
|
|
|
@@ -358,7 +359,7 @@ export default class NodeClient extends Client {
|
|
|
358
359
|
* @returns {(address: string, cert?: string) => NodeChannel}
|
|
359
360
|
*/
|
|
360
361
|
_createNetworkChannel() {
|
|
361
|
-
return (address) => new NodeChannel(address, this.
|
|
362
|
+
return (address) => new NodeChannel(address, this.grpcDeadline);
|
|
362
363
|
}
|
|
363
364
|
|
|
364
365
|
/**
|
package/src/client/WebClient.js
CHANGED
|
@@ -27,52 +27,45 @@ export default class WebClient extends Client {
|
|
|
27
27
|
*/
|
|
28
28
|
constructor(props) {
|
|
29
29
|
super(props);
|
|
30
|
+
|
|
30
31
|
if (props != null) {
|
|
31
32
|
if (typeof props.network === "string") {
|
|
32
|
-
|
|
33
|
+
this._setNetworkFromName(props.network);
|
|
34
|
+
} else if (props.network != null) {
|
|
35
|
+
Client._validateNetworkConsistency(props.network);
|
|
36
|
+
|
|
37
|
+
const { shard, realm } = Client._extractShardRealm(
|
|
38
|
+
props.network,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
// Shard and realm are inferred from the network, so we need to set them here
|
|
42
|
+
// to ensure that the client is properly configured.
|
|
43
|
+
this._shard = shard;
|
|
44
|
+
this._realm = realm;
|
|
45
|
+
|
|
46
|
+
this.setNetwork(props.network);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (typeof props.mirrorNetwork === "string") {
|
|
50
|
+
switch (props.mirrorNetwork) {
|
|
33
51
|
case "mainnet":
|
|
34
|
-
this.setNetwork(WebNetwork.MAINNET);
|
|
35
52
|
this.setMirrorNetwork(WebMirrorNetwork.MAINNET);
|
|
36
|
-
this.setLedgerId(LedgerId.MAINNET);
|
|
37
53
|
break;
|
|
38
54
|
|
|
39
55
|
case "testnet":
|
|
40
|
-
this.setNetwork(WebNetwork.TESTNET);
|
|
41
|
-
this.setLedgerId(LedgerId.TESTNET);
|
|
42
56
|
this.setMirrorNetwork(WebMirrorNetwork.TESTNET);
|
|
43
57
|
break;
|
|
44
58
|
|
|
45
59
|
case "previewnet":
|
|
46
|
-
this.setNetwork(WebNetwork.PREVIEWNET);
|
|
47
|
-
this.setLedgerId(LedgerId.PREVIEWNET);
|
|
48
60
|
this.setMirrorNetwork(WebMirrorNetwork.PREVIEWNET);
|
|
49
61
|
break;
|
|
50
62
|
|
|
51
|
-
case "local-node":
|
|
52
|
-
this.setNetwork(WebNetwork.LOCAL_NODE);
|
|
53
|
-
this.setLedgerId(LedgerId.LOCAL_NODE);
|
|
54
|
-
this.setMirrorNetwork(WebMirrorNetwork.LOCAL_NODE);
|
|
55
|
-
break;
|
|
56
|
-
|
|
57
63
|
default:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
`unknown network: ${props.network}`,
|
|
61
|
-
);
|
|
64
|
+
this.setMirrorNetwork([props.mirrorNetwork]);
|
|
65
|
+
break;
|
|
62
66
|
}
|
|
63
|
-
} else if (props.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const { shard, realm } = Client._extractShardRealm(
|
|
67
|
-
props.network,
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
// Shard and realm are inferred from the network, so we need to set them here
|
|
71
|
-
// to ensure that the client is properly configured.
|
|
72
|
-
this._shard = shard;
|
|
73
|
-
this._realm = realm;
|
|
74
|
-
|
|
75
|
-
this.setNetwork(props.network);
|
|
67
|
+
} else if (props.mirrorNetwork != null) {
|
|
68
|
+
this.setMirrorNetwork(props.mirrorNetwork);
|
|
76
69
|
}
|
|
77
70
|
}
|
|
78
71
|
}
|
|
@@ -249,6 +242,19 @@ export default class WebClient extends Client {
|
|
|
249
242
|
break;
|
|
250
243
|
}
|
|
251
244
|
} else {
|
|
245
|
+
// Check for deprecation warnings for network endpoints with schemes
|
|
246
|
+
for (const [key] of Object.entries(network)) {
|
|
247
|
+
if (key.startsWith("https://") || key.startsWith("http://")) {
|
|
248
|
+
console.warn(
|
|
249
|
+
'[Deprecation Notice] Hiero SDK: Network endpoint "' +
|
|
250
|
+
key +
|
|
251
|
+
'" includes a URL scheme (e.g. "https://"). ' +
|
|
252
|
+
"This format was accepted in earlier versions but is now deprecated. " +
|
|
253
|
+
'Please remove the scheme and use "host:port" instead (e.g. "node00.swirldslabs.com:443"). ' +
|
|
254
|
+
"Support for scheme-prefixed endpoints will be removed in a future major release.",
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
252
258
|
this._network.setNetwork(network);
|
|
253
259
|
}
|
|
254
260
|
}
|
|
@@ -282,6 +288,46 @@ export default class WebClient extends Client {
|
|
|
282
288
|
return this;
|
|
283
289
|
}
|
|
284
290
|
|
|
291
|
+
/**
|
|
292
|
+
* @private
|
|
293
|
+
* @param {string} name
|
|
294
|
+
* @returns {this}
|
|
295
|
+
*/
|
|
296
|
+
_setNetworkFromName(name) {
|
|
297
|
+
switch (name) {
|
|
298
|
+
case "mainnet":
|
|
299
|
+
this.setNetwork(WebNetwork.MAINNET);
|
|
300
|
+
this.setMirrorNetwork(WebMirrorNetwork.MAINNET);
|
|
301
|
+
this.setLedgerId(LedgerId.MAINNET);
|
|
302
|
+
break;
|
|
303
|
+
|
|
304
|
+
case "testnet":
|
|
305
|
+
this.setNetwork(WebNetwork.TESTNET);
|
|
306
|
+
this.setMirrorNetwork(WebMirrorNetwork.TESTNET);
|
|
307
|
+
this.setLedgerId(LedgerId.TESTNET);
|
|
308
|
+
break;
|
|
309
|
+
|
|
310
|
+
case "previewnet":
|
|
311
|
+
this.setNetwork(WebNetwork.PREVIEWNET);
|
|
312
|
+
this.setMirrorNetwork(WebMirrorNetwork.PREVIEWNET);
|
|
313
|
+
this.setLedgerId(LedgerId.PREVIEWNET);
|
|
314
|
+
break;
|
|
315
|
+
|
|
316
|
+
case "local-node":
|
|
317
|
+
this.setNetwork(WebNetwork.LOCAL_NODE);
|
|
318
|
+
this.setMirrorNetwork(WebMirrorNetwork.LOCAL_NODE);
|
|
319
|
+
this.setLedgerId(LedgerId.LOCAL_NODE);
|
|
320
|
+
break;
|
|
321
|
+
|
|
322
|
+
default:
|
|
323
|
+
throw new Error(
|
|
324
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
325
|
+
`unknown network: ${name}`,
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
return this;
|
|
329
|
+
}
|
|
330
|
+
|
|
285
331
|
/**
|
|
286
332
|
* @override
|
|
287
333
|
* @returns {Promise<this>}
|
|
@@ -331,7 +377,7 @@ export default class WebClient extends Client {
|
|
|
331
377
|
* @returns {(address: string) => WebChannel}
|
|
332
378
|
*/
|
|
333
379
|
_createNetworkChannel() {
|
|
334
|
-
return (address) => new WebChannel(address);
|
|
380
|
+
return (address) => new WebChannel(address, this.grpcDeadline);
|
|
335
381
|
}
|
|
336
382
|
|
|
337
383
|
/**
|