@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.
Files changed (75) hide show
  1. package/dist/umd.js +440 -71
  2. package/dist/umd.min.js +14 -14
  3. package/lib/Executable.cjs +13 -3
  4. package/lib/Executable.js +1 -1
  5. package/lib/Executable.js.map +1 -1
  6. package/lib/channel/Channel.cjs +25 -1
  7. package/lib/channel/Channel.d.ts +20 -0
  8. package/lib/channel/Channel.js +1 -1
  9. package/lib/channel/Channel.js.map +1 -1
  10. package/lib/channel/NativeChannel.cjs +96 -2
  11. package/lib/channel/NativeChannel.d.ts +21 -1
  12. package/lib/channel/NativeChannel.js +1 -1
  13. package/lib/channel/NativeChannel.js.map +1 -1
  14. package/lib/channel/NodeChannel.cjs +4 -5
  15. package/lib/channel/NodeChannel.d.ts +2 -3
  16. package/lib/channel/NodeChannel.js +1 -1
  17. package/lib/channel/NodeChannel.js.map +1 -1
  18. package/lib/channel/WebChannel.cjs +163 -4
  19. package/lib/channel/WebChannel.d.ts +51 -1
  20. package/lib/channel/WebChannel.js +1 -1
  21. package/lib/channel/WebChannel.js.map +1 -1
  22. package/lib/client/Client.cjs +62 -5
  23. package/lib/client/Client.d.ts +26 -3
  24. package/lib/client/Client.js +1 -1
  25. package/lib/client/Client.js.map +1 -1
  26. package/lib/client/NativeClient.cjs +1 -1
  27. package/lib/client/NativeClient.js +1 -1
  28. package/lib/client/NativeClient.js.map +1 -1
  29. package/lib/client/NodeClient.cjs +7 -6
  30. package/lib/client/NodeClient.d.ts +3 -3
  31. package/lib/client/NodeClient.js +1 -1
  32. package/lib/client/NodeClient.js.map +1 -1
  33. package/lib/client/WebClient.cjs +61 -27
  34. package/lib/client/WebClient.d.ts +6 -0
  35. package/lib/client/WebClient.js +1 -1
  36. package/lib/client/WebClient.js.map +1 -1
  37. package/lib/client/addressbooks/mainnet.cjs +1 -1
  38. package/lib/client/addressbooks/mainnet.d.ts +1 -1
  39. package/lib/client/addressbooks/mainnet.js +1 -1
  40. package/lib/client/addressbooks/mainnet.js.map +1 -1
  41. package/lib/client/addressbooks/previewnet.cjs +1 -1
  42. package/lib/client/addressbooks/previewnet.d.ts +1 -1
  43. package/lib/client/addressbooks/previewnet.js +1 -1
  44. package/lib/client/addressbooks/previewnet.js.map +1 -1
  45. package/lib/client/addressbooks/testnet.cjs +1 -1
  46. package/lib/client/addressbooks/testnet.d.ts +1 -1
  47. package/lib/client/addressbooks/testnet.js +1 -1
  48. package/lib/client/addressbooks/testnet.js.map +1 -1
  49. package/lib/constants/ClientConstants.cjs +18 -2
  50. package/lib/constants/ClientConstants.d.ts +15 -0
  51. package/lib/constants/ClientConstants.js +1 -1
  52. package/lib/constants/ClientConstants.js.map +1 -1
  53. package/lib/network/AddressBookQuery.cjs +0 -4
  54. package/lib/network/AddressBookQuery.js +1 -1
  55. package/lib/network/AddressBookQuery.js.map +1 -1
  56. package/lib/network/AddressBookQueryWeb.cjs +1 -5
  57. package/lib/network/AddressBookQueryWeb.js +1 -1
  58. package/lib/network/AddressBookQueryWeb.js.map +1 -1
  59. package/lib/version.js +1 -1
  60. package/package.json +9 -9
  61. package/src/Executable.js +18 -2
  62. package/src/channel/Channel.js +25 -1
  63. package/src/channel/NativeChannel.js +111 -2
  64. package/src/channel/NodeChannel.js +4 -7
  65. package/src/channel/WebChannel.js +189 -9
  66. package/src/client/Client.js +79 -5
  67. package/src/client/NativeClient.js +1 -1
  68. package/src/client/NodeClient.js +7 -6
  69. package/src/client/WebClient.js +77 -31
  70. package/src/client/addressbooks/mainnet.js +1 -1
  71. package/src/client/addressbooks/previewnet.js +1 -1
  72. package/src/client/addressbooks/testnet.js +1 -1
  73. package/src/constants/ClientConstants.js +17 -1
  74. package/src/network/AddressBookQuery.js +0 -7
  75. package/src/network/AddressBookQueryWeb.js +1 -8
package/dist/umd.js CHANGED
@@ -5119,7 +5119,11 @@
5119
5119
  var f = n.default;
5120
5120
  if (typeof f == "function") {
5121
5121
  var a = function a () {
5122
- if (this instanceof a) {
5122
+ var isInstance = false;
5123
+ try {
5124
+ isInstance = this instanceof a;
5125
+ } catch {}
5126
+ if (isInstance) {
5123
5127
  return Reflect.construct(f, arguments, this.constructor);
5124
5128
  }
5125
5129
  return f.apply(this, arguments);
@@ -43555,6 +43559,7 @@
43555
43559
  if (error instanceof GrpcServiceError) {
43556
43560
  return (
43557
43561
  error.status._code === GrpcStatus.Timeout._code ||
43562
+ error.status._code === GrpcStatus.DeadlineExceeded._code ||
43558
43563
  error.status._code === GrpcStatus.Unavailable._code ||
43559
43564
  error.status._code === GrpcStatus.ResourceExhausted._code ||
43560
43565
  error.status._code === GrpcStatus.GrpcWeb._code ||
@@ -43645,6 +43650,11 @@
43645
43650
  requestTimeout != null ? requestTimeout : client.requestTimeout;
43646
43651
  }
43647
43652
 
43653
+ // If the grpc deadline is not set on the request, use the default value from client
43654
+ if (this._grpcDeadline == null) {
43655
+ this._grpcDeadline = client.grpcDeadline;
43656
+ }
43657
+
43648
43658
  // Some request need to perform additional requests before the executing
43649
43659
  // such as paid queries need to fetch the cost of the query before
43650
43660
  // finally executing the actual query.
@@ -43762,6 +43772,12 @@
43762
43772
  }
43763
43773
 
43764
43774
  const channel = node.getChannel();
43775
+
43776
+ // Set the gRPC deadline on the channel if this query has a custom deadline
43777
+ if (this._grpcDeadline != null) {
43778
+ channel.setGrpcDeadline(this._grpcDeadline);
43779
+ }
43780
+
43765
43781
  const request = await this._makeRequestAsync();
43766
43782
 
43767
43783
  let response;
@@ -43812,7 +43828,7 @@
43812
43828
  // from blocking this request
43813
43829
  const promises = [];
43814
43830
 
43815
- // If a grpc deadline is est, we should race it, otherwise the only thing in the
43831
+ // If a grpc deadline is set, we should race it, otherwise the only thing in the
43816
43832
  // list of promises will be the execution promise.
43817
43833
  if (this._grpcDeadline != null) {
43818
43834
  promises.push(
@@ -43821,7 +43837,11 @@
43821
43837
  setTimeout(
43822
43838
  // eslint-disable-next-line ie11/no-loop-func
43823
43839
  () =>
43824
- reject(new Error("grpc deadline exceeded")),
43840
+ reject(
43841
+ new GrpcServiceError(
43842
+ GrpcStatus.DeadlineExceeded,
43843
+ ),
43844
+ ),
43825
43845
  /** @type {number=} */ (this._grpcDeadline),
43826
43846
  ),
43827
43847
  ),
@@ -93070,6 +93090,7 @@
93070
93090
  transmit,
93071
93091
  serialize,
93072
93092
  asObject: opts.browser.asObject,
93093
+ asObjectBindingsOnly: opts.browser.asObjectBindingsOnly,
93073
93094
  formatters: opts.browser.formatters,
93074
93095
  levels,
93075
93096
  timestamp: getTimeFunction(opts),
@@ -93079,6 +93100,13 @@
93079
93100
  logger.levels = getLevels(opts);
93080
93101
  logger.level = level;
93081
93102
 
93103
+ logger.isLevelEnabled = function (level) {
93104
+ if (!this.levels.values[level]) {
93105
+ return false
93106
+ }
93107
+
93108
+ return this.levels.values[level] >= this.levels.values[this.level]
93109
+ };
93082
93110
  logger.setMaxListeners = logger.getMaxListeners =
93083
93111
  logger.emit = logger.addListener = logger.on =
93084
93112
  logger.prependListener = logger.once =
@@ -93278,7 +93306,7 @@
93278
93306
  argsIsSerialized = true;
93279
93307
  }
93280
93308
  if (opts.asObject || opts.formatters) {
93281
- write.call(proto, asObject(this, level, args, ts, opts));
93309
+ write.call(proto, ...asObject(this, level, args, ts, opts));
93282
93310
  } else write.apply(proto, args);
93283
93311
 
93284
93312
  if (opts.transmit) {
@@ -93307,6 +93335,10 @@
93307
93335
  const argsCloned = args.slice();
93308
93336
  let msg = argsCloned[0];
93309
93337
  const logObject = {};
93338
+
93339
+ let lvl = (logger._childLevel | 0) + 1;
93340
+ if (lvl < 1) lvl = 1;
93341
+
93310
93342
  if (ts) {
93311
93343
  logObject.time = ts;
93312
93344
  }
@@ -93318,19 +93350,28 @@
93318
93350
  logObject.level = logger.levels.values[level];
93319
93351
  }
93320
93352
 
93321
- let lvl = (logger._childLevel | 0) + 1;
93322
- if (lvl < 1) lvl = 1;
93323
- // deliberate, catching objects, arrays
93324
- if (msg !== null && typeof msg === 'object') {
93325
- while (lvl-- && typeof argsCloned[0] === 'object') {
93326
- Object.assign(logObject, argsCloned.shift());
93353
+ if (opts.asObjectBindingsOnly) {
93354
+ if (msg !== null && typeof msg === 'object') {
93355
+ while (lvl-- && typeof argsCloned[0] === 'object') {
93356
+ Object.assign(logObject, argsCloned.shift());
93357
+ }
93327
93358
  }
93328
- msg = argsCloned.length ? format(argsCloned.shift(), argsCloned) : undefined;
93329
- } else if (typeof msg === 'string') msg = format(argsCloned.shift(), argsCloned);
93330
- if (msg !== undefined) logObject[opts.messageKey] = msg;
93331
93359
 
93332
- const formattedLogObject = logObjectFormatter(logObject);
93333
- return formattedLogObject
93360
+ const formattedLogObject = logObjectFormatter(logObject);
93361
+ return [formattedLogObject, ...argsCloned]
93362
+ } else {
93363
+ // deliberate, catching objects, arrays
93364
+ if (msg !== null && typeof msg === 'object') {
93365
+ while (lvl-- && typeof argsCloned[0] === 'object') {
93366
+ Object.assign(logObject, argsCloned.shift());
93367
+ }
93368
+ msg = argsCloned.length ? format(argsCloned.shift(), argsCloned) : undefined;
93369
+ } else if (typeof msg === 'string') msg = format(argsCloned.shift(), argsCloned);
93370
+ if (msg !== undefined) logObject[opts.messageKey] = msg;
93371
+
93372
+ const formattedLogObject = logObjectFormatter(logObject);
93373
+ return [formattedLogObject]
93374
+ }
93334
93375
  }
93335
93376
 
93336
93377
  function applySerializers (args, serialize, serializers, stdErrSerialize) {
@@ -96869,6 +96910,22 @@
96869
96910
 
96870
96911
  /* NOSONAR */
96871
96912
 
96913
+ /**
96914
+ * Default gRPC deadline in milliseconds (10 seconds)
96915
+ *
96916
+ * Maximum time allowed for a single gRPC request. If exceeded, the node
96917
+ * is marked unhealthy and the SDK rotates to the next node.
96918
+ */
96919
+ const DEFAULT_GRPC_DEADLINE = 10 * 1000;
96920
+
96921
+ /**
96922
+ * Default request timeout in milliseconds (2 minutes)
96923
+ *
96924
+ * Maximum total time for a complete Transaction/Query operation including
96925
+ * retries and node rotation. Must be >= grpcDeadline.
96926
+ */
96927
+ const DEFAULT_REQUEST_TIMEOUT = 2 * 60 * 1000;
96928
+
96872
96929
  // MAINNET node proxies are the same for both 'WebClient' and 'NativeClient'
96873
96930
  const MAINNET = {
96874
96931
  "node00.swirldslabs.com:443": new AccountId(3),
@@ -96899,7 +96956,7 @@
96899
96956
  "node29.swirldslabs.com:443": new AccountId(32),
96900
96957
  "node30.swirldslabs.com:443": new AccountId(33),
96901
96958
  "node31.swirldslabs.com:443": new AccountId(34),
96902
- // "node32.swirldslabs.com:443": new AccountId(35), - temporarily disabled
96959
+ "node32.swirldslabs.com:443": new AccountId(35),
96903
96960
  "node33.swirldslabs.com:443": new AccountId(36),
96904
96961
  "node34.swirldslabs.com:443": new AccountId(37),
96905
96962
  };
@@ -97184,13 +97241,6 @@
97184
97241
  * @returns {Promise<NodeAddressBook>}
97185
97242
  */
97186
97243
  execute(client, requestTimeout) {
97187
- // Extra validation when initializing the client with only a mirror network
97188
- if (client._network._network.size === 0 && !client._timer) {
97189
- throw new Error(
97190
- "The client's network update period is required. Please set it using the setNetworkUpdatePeriod method.",
97191
- );
97192
- }
97193
-
97194
97244
  return new Promise((resolve, reject) => {
97195
97245
  void this._makeFetchRequest(
97196
97246
  client,
@@ -97281,7 +97331,7 @@
97281
97331
  certHash: node.node_cert_hash,
97282
97332
  publicKey: node.public_key,
97283
97333
  description: node.description,
97284
- stake: node.stake.toString(),
97334
+ stake: node.stake?.toString(),
97285
97335
  }),
97286
97336
  );
97287
97337
 
@@ -97437,6 +97487,8 @@
97437
97487
  * @property {boolean} [scheduleNetworkUpdate]
97438
97488
  * @property {number} [shard]
97439
97489
  * @property {number} [realm]
97490
+ * @property {number} [grpcDeadline]
97491
+ * @property {number} [requestTimeout]
97440
97492
  */
97441
97493
 
97442
97494
  /**
@@ -97524,7 +97576,10 @@
97524
97576
  this._defaultRegenerateTransactionId = true;
97525
97577
 
97526
97578
  /** @private */
97527
- this._requestTimeout = null;
97579
+ this._requestTimeout = DEFAULT_REQUEST_TIMEOUT;
97580
+
97581
+ /** @private */
97582
+ this._grpcDeadline = DEFAULT_GRPC_DEADLINE;
97528
97583
 
97529
97584
  /**
97530
97585
  * @type {boolean}
@@ -97553,6 +97608,23 @@
97553
97608
  this._realm = props.realm;
97554
97609
  }
97555
97610
 
97611
+ if (props != null && props.grpcDeadline != null) {
97612
+ this.setGrpcDeadline(props.grpcDeadline);
97613
+ }
97614
+
97615
+ if (props != null && props.requestTimeout != null) {
97616
+ this.setRequestTimeout(props.requestTimeout);
97617
+ }
97618
+
97619
+ // Validate that requestTimeout is larger than grpcDeadline after both are set
97620
+ if (this._requestTimeout <= this._grpcDeadline) {
97621
+ console.warn(
97622
+ `DEPRECATION WARNING: requestTimeout (${this._requestTimeout}ms) should be larger than grpcDeadline (${this._grpcDeadline}ms). ` +
97623
+ `This configuration may cause operations to fail unexpectedly. ` +
97624
+ `This will throw an error in the next major version. Please adjust your timeout values.`,
97625
+ );
97626
+ }
97627
+
97556
97628
  /** @internal */
97557
97629
  /** @type {NodeJS.Timeout} */
97558
97630
  this._timer;
@@ -98072,21 +98144,65 @@
98072
98144
  }
98073
98145
 
98074
98146
  /**
98075
- * @param {number} requestTimeout - Number of milliseconds
98147
+ * Set the total request timeout for complete operations.
98148
+ *
98149
+ * @param {number} requestTimeout - Maximum time in milliseconds for complete Transaction/Query operations
98076
98150
  * @returns {this}
98077
98151
  */
98078
98152
  setRequestTimeout(requestTimeout) {
98153
+ if (requestTimeout <= 0) {
98154
+ throw new Error("requestTimeout must be a positive number");
98155
+ }
98156
+ if (requestTimeout <= this._grpcDeadline) {
98157
+ console.warn(
98158
+ `DEPRECATION WARNING: requestTimeout (${requestTimeout}ms) should be larger than grpcDeadline (${this._grpcDeadline}ms). ` +
98159
+ `This configuration may cause operations to fail unexpectedly. ` +
98160
+ `This will throw an error in the next major version. Please adjust your timeout values.`,
98161
+ );
98162
+ }
98079
98163
  this._requestTimeout = requestTimeout;
98080
98164
  return this;
98081
98165
  }
98082
98166
 
98083
98167
  /**
98084
- * @returns {?number}
98168
+ * Get the total request timeout for complete operations.
98169
+ *
98170
+ * @returns {number} Maximum time in milliseconds for complete Transaction/Query operations
98085
98171
  */
98086
98172
  get requestTimeout() {
98087
98173
  return this._requestTimeout;
98088
98174
  }
98089
98175
 
98176
+ /**
98177
+ * Set the global gRPC deadline for all requests.
98178
+ *
98179
+ * @param {number} grpcDeadline - Maximum time in milliseconds for a single gRPC request
98180
+ * @returns {this}
98181
+ */
98182
+ setGrpcDeadline(grpcDeadline) {
98183
+ if (grpcDeadline <= 0) {
98184
+ throw new Error("grpcDeadline must be a positive number");
98185
+ }
98186
+ if (grpcDeadline >= this._requestTimeout) {
98187
+ console.warn(
98188
+ `DEPRECATION WARNING: grpcDeadline (${grpcDeadline}ms) should be smaller than requestTimeout (${this._requestTimeout}ms). ` +
98189
+ `This configuration may cause operations to fail unexpectedly. ` +
98190
+ `This will throw an error in the next major version. Please adjust your timeout values.`,
98191
+ );
98192
+ }
98193
+ this._grpcDeadline = grpcDeadline;
98194
+ return this;
98195
+ }
98196
+
98197
+ /**
98198
+ * Get the global gRPC deadline for all requests.
98199
+ *
98200
+ * @returns {number} Maximum time in milliseconds for a single gRPC request
98201
+ */
98202
+ get grpcDeadline() {
98203
+ return this._grpcDeadline;
98204
+ }
98205
+
98090
98206
  /**
98091
98207
  * @returns {number}
98092
98208
  */
@@ -98191,7 +98307,9 @@
98191
98307
  * @returns {(address: string) => ChannelT}
98192
98308
  */
98193
98309
  _createNetworkChannel() {
98194
- throw new Error("not implemented");
98310
+ return () => {
98311
+ throw new Error("not implemented");
98312
+ };
98195
98313
  }
98196
98314
 
98197
98315
  /**
@@ -98199,7 +98317,9 @@
98199
98317
  * @returns {(address: string) => MirrorChannelT}
98200
98318
  */
98201
98319
  _createMirrorNetworkChannel() {
98202
- throw new Error("not implemented");
98320
+ return () => {
98321
+ throw new Error("not implemented");
98322
+ };
98203
98323
  }
98204
98324
 
98205
98325
  /**
@@ -98288,7 +98408,7 @@
98288
98408
 
98289
98409
  const SDK_NAME = "hiero-sdk-js";
98290
98410
  const SDK_VERSION =
98291
- "2.75.0" ;
98411
+ "2.77.0" ;
98292
98412
 
98293
98413
  // SPDX-License-Identifier: Apache-2.0
98294
98414
 
@@ -98302,8 +98422,9 @@
98302
98422
  class Channel {
98303
98423
  /**
98304
98424
  * @protected
98425
+ * @param {number} [grpcDeadline] - The gRPC deadline in milliseconds
98305
98426
  */
98306
- constructor() {
98427
+ constructor(grpcDeadline = DEFAULT_GRPC_DEADLINE) {
98307
98428
  /**
98308
98429
  * @protected
98309
98430
  * @type {?HieroProto.proto.CryptoService}
@@ -98363,6 +98484,28 @@
98363
98484
  * @type {?HieroProto.proto.AddressBookService}
98364
98485
  */
98365
98486
  this._addressBook = null;
98487
+
98488
+ /**
98489
+ * @protected
98490
+ * @type {number}
98491
+ */
98492
+ this._grpcDeadline = grpcDeadline;
98493
+ }
98494
+
98495
+ /**
98496
+ * Set the gRPC deadline for this channel
98497
+ * @param {number} deadline - The deadline in milliseconds, or null to clear
98498
+ */
98499
+ setGrpcDeadline(deadline) {
98500
+ this._grpcDeadline = deadline;
98501
+ }
98502
+
98503
+ /**
98504
+ * Get the gRPC deadline for this channel
98505
+ * @returns {number}
98506
+ */
98507
+ get grpcDeadline() {
98508
+ return this._grpcDeadline;
98366
98509
  }
98367
98510
 
98368
98511
  /**
@@ -98634,15 +98777,185 @@
98634
98777
  class WebChannel extends Channel {
98635
98778
  /**
98636
98779
  * @param {string} address
98780
+ * @param {number=} grpcDeadline
98637
98781
  */
98638
- constructor(address) {
98639
- super();
98782
+ constructor(address, grpcDeadline) {
98783
+ super(grpcDeadline);
98640
98784
 
98641
98785
  /**
98642
98786
  * @type {string}
98643
98787
  * @private
98644
98788
  */
98645
98789
  this._address = address;
98790
+
98791
+ // Set the gRPC deadline using the base class method
98792
+
98793
+ /**
98794
+ * Flag indicating if the connection is ready (health check has passed)
98795
+ * Set to true after the first successful health check
98796
+ *
98797
+ * @type {boolean}
98798
+ * @private
98799
+ */
98800
+ this._isReady = false;
98801
+
98802
+ /**
98803
+ * Promise that resolves when the health check is complete
98804
+ * Used to prevent multiple concurrent health checks
98805
+ *
98806
+ * @type {Promise<void>|null}
98807
+ * @private
98808
+ */
98809
+ this._healthCheckPromise = null;
98810
+ }
98811
+
98812
+ /**
98813
+ * Determines whether to use HTTPS based on the address
98814
+ * @param {string} address - The address to check
98815
+ * @returns {boolean} - True if HTTPS should be used, false for HTTP
98816
+ * @private
98817
+ */
98818
+ _shouldUseHttps(address) {
98819
+ return !(
98820
+ address.includes("localhost") || address.includes("127.0.0.1")
98821
+ );
98822
+ }
98823
+
98824
+ /**
98825
+ * Builds the full URL with appropriate scheme (http/https)
98826
+ * @param {string} address - The base address
98827
+ * @returns {string} - The full URL with scheme
98828
+ * @private
98829
+ */
98830
+ _buildUrl(address) {
98831
+ // Check if address already contains a scheme
98832
+ const hasScheme =
98833
+ address.startsWith("http://") || address.startsWith("https://");
98834
+
98835
+ if (hasScheme) {
98836
+ // Use the address as-is if it already has a scheme
98837
+ return address;
98838
+ } else {
98839
+ // Only prepend scheme if none exists
98840
+ const shouldUseHttps = this._shouldUseHttps(address);
98841
+ return shouldUseHttps ? `https://${address}` : `http://${address}`;
98842
+ }
98843
+ }
98844
+
98845
+ /**
98846
+ * Check if the gRPC-Web proxy is reachable and healthy
98847
+ * Performs a POST request and verifies the response has gRPC-Web headers,
98848
+ * which indicates the proxy is running and processing gRPC requests.
98849
+ * Results are cached per address for the entire lifecycle.
98850
+ * Uses promise-based synchronization to prevent multiple concurrent health checks.
98851
+ *
98852
+ * @param {Date} deadline - Deadline for the health check
98853
+ * @returns {Promise<void>}
98854
+ * @private
98855
+ */
98856
+ async _waitForReady(deadline) {
98857
+ // Check if we've already validated this address
98858
+ if (this._isReady) {
98859
+ return; // Health check already passed for this address
98860
+ }
98861
+
98862
+ // If a health check is already in progress, wait for it to complete
98863
+ if (this._healthCheckPromise) {
98864
+ return this._healthCheckPromise;
98865
+ }
98866
+
98867
+ // Start a new health check and store the promise
98868
+ this._healthCheckPromise = this._performHealthCheck(deadline);
98869
+
98870
+ try {
98871
+ await this._healthCheckPromise;
98872
+ } finally {
98873
+ // Clear the promise when done (success or failure)
98874
+ this._healthCheckPromise = null;
98875
+ }
98876
+ }
98877
+
98878
+ /**
98879
+ * Performs the actual health check request
98880
+ * @param {Date} deadline - Deadline for the health check
98881
+ * @returns {Promise<void>}
98882
+ * @private
98883
+ */
98884
+ async _performHealthCheck(deadline) {
98885
+ const address = this._buildUrl(this._address);
98886
+
98887
+ // Calculate remaining time until deadline
98888
+ const timeoutMs = deadline.getTime() - Date.now();
98889
+ if (timeoutMs <= 0) {
98890
+ throw new GrpcServiceError(
98891
+ GrpcStatus.Timeout,
98892
+ ALL_WEB_NETWORK_NODES?.[this._address]?.toString(),
98893
+ );
98894
+ }
98895
+
98896
+ const abortController = new AbortController();
98897
+ const timeoutId = setTimeout(() => abortController.abort(), timeoutMs);
98898
+
98899
+ try {
98900
+ // Make a POST request to verify the gRPC-Web proxy is running
98901
+ // We use a minimal gRPC-Web compatible request
98902
+ //eslint-disable-next-line n/no-unsupported-features/node-builtins
98903
+ const response = await fetch(address, {
98904
+ method: "POST",
98905
+ headers: {
98906
+ "content-type": "application/grpc-web+proto",
98907
+ "x-user-agent": `${SDK_NAME}/${SDK_VERSION}`,
98908
+ "x-grpc-web": "1",
98909
+ },
98910
+ body: new Uint8Array(0), // Empty body for health check
98911
+ signal: abortController.signal,
98912
+ });
98913
+
98914
+ clearTimeout(timeoutId);
98915
+
98916
+ // Check if response is successful (200) or indicates a redirect (3xx)
98917
+ // 3xx status codes indicate the resource has moved, which is valid for proxies
98918
+ if (
98919
+ response.ok ||
98920
+ (response.status >= 300 && response.status < 400)
98921
+ ) {
98922
+ const grpcStatus = response.headers.get("grpc-status");
98923
+ const grpcMessage = response.headers.get("grpc-message");
98924
+
98925
+ // If gRPC headers exist, the proxy is running and processing requests
98926
+ if (grpcStatus != null || grpcMessage != null) {
98927
+ // Mark this connection as ready
98928
+ this._isReady = true;
98929
+ return; // Healthy - gRPC-Web proxy is responding
98930
+ }
98931
+ }
98932
+
98933
+ // If we get here, either status isn't 200/3xx or no gRPC headers present
98934
+ // This means the proxy might not be configured correctly or not running
98935
+ throw new GrpcServiceError(
98936
+ GrpcStatus.Unavailable,
98937
+ ALL_WEB_NETWORK_NODES?.[this._address]?.toString(),
98938
+ );
98939
+ } catch (error) {
98940
+ clearTimeout(timeoutId);
98941
+
98942
+ if (error instanceof Error && error.name === "AbortError") {
98943
+ throw new GrpcServiceError(
98944
+ GrpcStatus.Timeout,
98945
+ ALL_WEB_NETWORK_NODES?.[this._address]?.toString(),
98946
+ );
98947
+ }
98948
+
98949
+ if (error instanceof GrpcServiceError) {
98950
+ throw error;
98951
+ }
98952
+
98953
+ // Network error - server is not reachable
98954
+ throw new GrpcServiceError(
98955
+ GrpcStatus.Unavailable,
98956
+ ALL_WEB_NETWORK_NODES?.[this._address]?.toString(),
98957
+ );
98958
+ }
98646
98959
  }
98647
98960
 
98648
98961
  /**
@@ -98662,15 +98975,18 @@
98662
98975
  _createUnaryClient(serviceName) {
98663
98976
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
98664
98977
  return async (method, requestData, callback) => {
98978
+ // Calculate deadline for connection check
98979
+ const deadline = new Date();
98980
+ const milliseconds = this._grpcDeadline;
98981
+
98982
+ deadline.setMilliseconds(deadline.getMilliseconds() + milliseconds);
98983
+
98665
98984
  try {
98666
- const shouldUseHttps = !(
98667
- this._address.includes("localhost") ||
98668
- this._address.includes("127.0.0.1")
98669
- );
98985
+ // Wait for connection to be ready (similar to gRPC waitForReady)
98986
+ await this._waitForReady(deadline);
98670
98987
 
98671
- const address = shouldUseHttps
98672
- ? `https://${this._address}`
98673
- : `http://${this._address}`;
98988
+ // Build the full URL with appropriate scheme
98989
+ const address = this._buildUrl(this._address);
98674
98990
  // this will be executed in a browser environment so eslint is
98675
98991
  // disabled for the fetch call
98676
98992
  //eslint-disable-next-line n/no-unsupported-features/node-builtins
@@ -98692,6 +99008,7 @@
98692
99008
  HttpStatus._fromValue(response.status),
98693
99009
  );
98694
99010
  callback(error, null);
99011
+ return;
98695
99012
  }
98696
99013
 
98697
99014
  // Check headers for gRPC errors
@@ -98705,6 +99022,7 @@
98705
99022
  );
98706
99023
  error.message = grpcMessage;
98707
99024
  callback(error, null);
99025
+ return;
98708
99026
  }
98709
99027
 
98710
99028
  const responseBuffer = await response.arrayBuffer();
@@ -98712,6 +99030,11 @@
98712
99030
 
98713
99031
  callback(null, unaryResponse);
98714
99032
  } catch (error) {
99033
+ if (error instanceof GrpcServiceError) {
99034
+ callback(error, null);
99035
+ return;
99036
+ }
99037
+
98715
99038
  const err = new GrpcServiceError(
98716
99039
  // retry on grpc web errors
98717
99040
  GrpcStatus._fromValue(18),
@@ -98745,52 +99068,45 @@
98745
99068
  */
98746
99069
  constructor(props) {
98747
99070
  super(props);
99071
+
98748
99072
  if (props != null) {
98749
99073
  if (typeof props.network === "string") {
98750
- switch (props.network) {
99074
+ this._setNetworkFromName(props.network);
99075
+ } else if (props.network != null) {
99076
+ Client._validateNetworkConsistency(props.network);
99077
+
99078
+ const { shard, realm } = Client._extractShardRealm(
99079
+ props.network,
99080
+ );
99081
+
99082
+ // Shard and realm are inferred from the network, so we need to set them here
99083
+ // to ensure that the client is properly configured.
99084
+ this._shard = shard;
99085
+ this._realm = realm;
99086
+
99087
+ this.setNetwork(props.network);
99088
+ }
99089
+
99090
+ if (typeof props.mirrorNetwork === "string") {
99091
+ switch (props.mirrorNetwork) {
98751
99092
  case "mainnet":
98752
- this.setNetwork(WebNetwork.MAINNET);
98753
99093
  this.setMirrorNetwork(WebMirrorNetwork.MAINNET);
98754
- this.setLedgerId(LedgerId.MAINNET);
98755
99094
  break;
98756
99095
 
98757
99096
  case "testnet":
98758
- this.setNetwork(WebNetwork.TESTNET);
98759
- this.setLedgerId(LedgerId.TESTNET);
98760
99097
  this.setMirrorNetwork(WebMirrorNetwork.TESTNET);
98761
99098
  break;
98762
99099
 
98763
99100
  case "previewnet":
98764
- this.setNetwork(WebNetwork.PREVIEWNET);
98765
- this.setLedgerId(LedgerId.PREVIEWNET);
98766
99101
  this.setMirrorNetwork(WebMirrorNetwork.PREVIEWNET);
98767
99102
  break;
98768
99103
 
98769
- case "local-node":
98770
- this.setNetwork(WebNetwork.LOCAL_NODE);
98771
- this.setLedgerId(LedgerId.LOCAL_NODE);
98772
- this.setMirrorNetwork(WebMirrorNetwork.LOCAL_NODE);
98773
- break;
98774
-
98775
99104
  default:
98776
- throw new Error(
98777
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
98778
- `unknown network: ${props.network}`,
98779
- );
99105
+ this.setMirrorNetwork([props.mirrorNetwork]);
99106
+ break;
98780
99107
  }
98781
- } else if (props.network != null) {
98782
- Client._validateNetworkConsistency(props.network);
98783
-
98784
- const { shard, realm } = Client._extractShardRealm(
98785
- props.network,
98786
- );
98787
-
98788
- // Shard and realm are inferred from the network, so we need to set them here
98789
- // to ensure that the client is properly configured.
98790
- this._shard = shard;
98791
- this._realm = realm;
98792
-
98793
- this.setNetwork(props.network);
99108
+ } else if (props.mirrorNetwork != null) {
99109
+ this.setMirrorNetwork(props.mirrorNetwork);
98794
99110
  }
98795
99111
  }
98796
99112
  }
@@ -98967,6 +99283,19 @@
98967
99283
  break;
98968
99284
  }
98969
99285
  } else {
99286
+ // Check for deprecation warnings for network endpoints with schemes
99287
+ for (const [key] of Object.entries(network)) {
99288
+ if (key.startsWith("https://") || key.startsWith("http://")) {
99289
+ console.warn(
99290
+ '[Deprecation Notice] Hiero SDK: Network endpoint "' +
99291
+ key +
99292
+ '" includes a URL scheme (e.g. "https://"). ' +
99293
+ "This format was accepted in earlier versions but is now deprecated. " +
99294
+ 'Please remove the scheme and use "host:port" instead (e.g. "node00.swirldslabs.com:443"). ' +
99295
+ "Support for scheme-prefixed endpoints will be removed in a future major release.",
99296
+ );
99297
+ }
99298
+ }
98970
99299
  this._network.setNetwork(network);
98971
99300
  }
98972
99301
  }
@@ -99000,6 +99329,46 @@
99000
99329
  return this;
99001
99330
  }
99002
99331
 
99332
+ /**
99333
+ * @private
99334
+ * @param {string} name
99335
+ * @returns {this}
99336
+ */
99337
+ _setNetworkFromName(name) {
99338
+ switch (name) {
99339
+ case "mainnet":
99340
+ this.setNetwork(WebNetwork.MAINNET);
99341
+ this.setMirrorNetwork(WebMirrorNetwork.MAINNET);
99342
+ this.setLedgerId(LedgerId.MAINNET);
99343
+ break;
99344
+
99345
+ case "testnet":
99346
+ this.setNetwork(WebNetwork.TESTNET);
99347
+ this.setMirrorNetwork(WebMirrorNetwork.TESTNET);
99348
+ this.setLedgerId(LedgerId.TESTNET);
99349
+ break;
99350
+
99351
+ case "previewnet":
99352
+ this.setNetwork(WebNetwork.PREVIEWNET);
99353
+ this.setMirrorNetwork(WebMirrorNetwork.PREVIEWNET);
99354
+ this.setLedgerId(LedgerId.PREVIEWNET);
99355
+ break;
99356
+
99357
+ case "local-node":
99358
+ this.setNetwork(WebNetwork.LOCAL_NODE);
99359
+ this.setMirrorNetwork(WebMirrorNetwork.LOCAL_NODE);
99360
+ this.setLedgerId(LedgerId.LOCAL_NODE);
99361
+ break;
99362
+
99363
+ default:
99364
+ throw new Error(
99365
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
99366
+ `unknown network: ${name}`,
99367
+ );
99368
+ }
99369
+ return this;
99370
+ }
99371
+
99003
99372
  /**
99004
99373
  * @override
99005
99374
  * @returns {Promise<this>}
@@ -99049,7 +99418,7 @@
99049
99418
  * @returns {(address: string) => WebChannel}
99050
99419
  */
99051
99420
  _createNetworkChannel() {
99052
- return (address) => new WebChannel(address);
99421
+ return (address) => new WebChannel(address, this.grpcDeadline);
99053
99422
  }
99054
99423
 
99055
99424
  /**