@injectivelabs/sdk-ts 1.19.26 → 1.19.28

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.
@@ -262,6 +262,392 @@ const getTxRawFromTxRawOrDirectSignResponse = (txRawOrDirectSignResponse) => {
262
262
  return txRawOrDirectSignResponse.signed === void 0 ? txRawOrDirectSignResponse : createTxRawFromSigResponse(txRawOrDirectSignResponse);
263
263
  };
264
264
 
265
+ //#endregion
266
+ //#region src/core/tx/types/tx.ts
267
+ const TxInclusionStrategy = {
268
+ Poll: "poll",
269
+ TendermintEvent: "tendermint-event",
270
+ TendermintEventAndPoll: "tendermint-event-and-poll"
271
+ };
272
+ const TxClientMode = {
273
+ gRpc: "grpc",
274
+ rest: "rest"
275
+ };
276
+
277
+ //#endregion
278
+ //#region src/core/tx/api/TxEventInclusion.ts
279
+ function normalizeTendermintWebSocketEndpoint(endpoint) {
280
+ let normalized = endpoint;
281
+ if (normalized.startsWith("http://")) normalized = `ws://${normalized.slice(7)}`;
282
+ else if (normalized.startsWith("https://")) normalized = `wss://${normalized.slice(8)}`;
283
+ return normalized.endsWith("/websocket") ? normalized : `${normalized.replace(/\/$/, "")}/websocket`;
284
+ }
285
+ async function subscribeToTendermintTxEvent({ txHash, timeout, endpoint, webSocketFactory }) {
286
+ const normalizedTxHash = normalizeTendermintTxHash(txHash);
287
+ const socket = createTendermintSocket(normalizeTendermintWebSocketEndpoint(endpoint), webSocketFactory);
288
+ const query = `tm.event='Tx' AND tx.hash='${normalizedTxHash}'`;
289
+ const requestId = `tx-event-${Date.now()}-${Math.random()}`;
290
+ return new Promise((resolve, reject) => {
291
+ let ready = false;
292
+ let waitSettled = false;
293
+ let closedIntentionally = false;
294
+ let timeoutId;
295
+ let waitResolve;
296
+ let waitReject;
297
+ const waitPromise = new Promise((resolveWait$1, rejectWait$1) => {
298
+ waitResolve = resolveWait$1;
299
+ waitReject = rejectWait$1;
300
+ });
301
+ const resolveSubscription = () => {
302
+ if (ready) return;
303
+ ready = true;
304
+ resolve({
305
+ close: cleanup,
306
+ wait: () => waitPromise
307
+ });
308
+ };
309
+ const cleanup = () => {
310
+ closedIntentionally = true;
311
+ clearTimeout(timeoutId);
312
+ socket.removeEventListener("open", onOpen);
313
+ socket.removeEventListener("message", onMessage);
314
+ socket.removeEventListener("error", onError);
315
+ socket.removeEventListener("close", onClose);
316
+ if (socket.readyState === 1 || socket.readyState === 0) socket.close();
317
+ };
318
+ const rejectWait = (error) => {
319
+ if (waitSettled) return;
320
+ waitSettled = true;
321
+ waitReject(error);
322
+ cleanup();
323
+ };
324
+ timeoutId = setTimeout(() => {
325
+ const error = /* @__PURE__ */ new Error(`Timed out waiting for Tendermint tx event after ${timeout}ms`);
326
+ if (ready) {
327
+ rejectWait(error);
328
+ return;
329
+ }
330
+ cleanup();
331
+ reject(error);
332
+ }, timeout);
333
+ const resolveWait = (response) => {
334
+ if (waitSettled) return;
335
+ waitSettled = true;
336
+ waitResolve(response);
337
+ cleanup();
338
+ };
339
+ const rejectForMessageError = (error) => {
340
+ if (ready) {
341
+ rejectWait(error);
342
+ return;
343
+ }
344
+ cleanup();
345
+ reject(error);
346
+ };
347
+ const onOpen = () => {
348
+ socket.send(JSON.stringify({
349
+ id: requestId,
350
+ jsonrpc: "2.0",
351
+ method: "subscribe",
352
+ params: { query }
353
+ }));
354
+ };
355
+ const onMessage = (event) => {
356
+ readMessageEventData(event).then((messageData) => {
357
+ const message = JSON.parse(messageData);
358
+ const eventResponse = parseTxEventResponse(message, normalizedTxHash);
359
+ if (eventResponse) {
360
+ resolveSubscription();
361
+ resolveWait(eventResponse);
362
+ return;
363
+ }
364
+ if (message.id !== requestId) return;
365
+ if (message.error) {
366
+ rejectForMessageError(/* @__PURE__ */ new Error(`Tendermint subscribe failed: ${JSON.stringify(message.error)}`));
367
+ return;
368
+ }
369
+ resolveSubscription();
370
+ }).catch((error) => {
371
+ rejectForMessageError(error instanceof Error ? error : /* @__PURE__ */ new Error(`Invalid Tendermint WebSocket JSON: ${String(error)}`));
372
+ });
373
+ };
374
+ const onError = () => {
375
+ const error = /* @__PURE__ */ new Error("Tendermint WebSocket error");
376
+ if (ready) {
377
+ rejectWait(error);
378
+ return;
379
+ }
380
+ cleanup();
381
+ reject(error);
382
+ };
383
+ const onClose = () => {
384
+ if (closedIntentionally) return;
385
+ const error = /* @__PURE__ */ new Error("Tendermint WebSocket closed");
386
+ if (ready) {
387
+ rejectWait(error);
388
+ return;
389
+ }
390
+ cleanup();
391
+ reject(error);
392
+ };
393
+ socket.addEventListener("open", onOpen);
394
+ socket.addEventListener("message", onMessage);
395
+ socket.addEventListener("error", onError);
396
+ socket.addEventListener("close", onClose);
397
+ });
398
+ }
399
+ function normalizeTendermintTxHash(txHash) {
400
+ if (!/^[0-9a-fA-F]{64}$/.test(txHash)) throw new Error("Invalid Tendermint tx hash");
401
+ return txHash.toUpperCase();
402
+ }
403
+ function createTendermintSocket(endpoint, webSocketFactory) {
404
+ if (webSocketFactory) return webSocketFactory(endpoint);
405
+ if (!globalThis.WebSocket) throw new Error("WebSocket is not available in this environment");
406
+ return new globalThis.WebSocket(endpoint);
407
+ }
408
+ async function readMessageEventData(event) {
409
+ const { data } = event;
410
+ if (typeof data === "string") return data;
411
+ if (typeof Blob !== "undefined" && data instanceof Blob) return data.text();
412
+ if (typeof ArrayBuffer !== "undefined" && data instanceof ArrayBuffer) return new TextDecoder().decode(data);
413
+ if (ArrayBuffer.isView(data)) return new TextDecoder().decode(data);
414
+ return String(data);
415
+ }
416
+ function parseTxEventResponse(message, txHash) {
417
+ var _message$params$resul, _message$params, _message$result, _data$value, _ref, _value$TxResult, _txResult$result;
418
+ const data = (_message$params$resul = message === null || message === void 0 || (_message$params = message.params) === null || _message$params === void 0 || (_message$params = _message$params.result) === null || _message$params === void 0 ? void 0 : _message$params.data) !== null && _message$params$resul !== void 0 ? _message$params$resul : message === null || message === void 0 || (_message$result = message.result) === null || _message$result === void 0 ? void 0 : _message$result.data;
419
+ const eventTxHashes = readTxEventHashes(data);
420
+ if (eventTxHashes.length > 0 && !eventTxHashes.some((eventTxHash) => eventTxHash.toUpperCase() === txHash.toUpperCase())) return;
421
+ const value = (_data$value = data === null || data === void 0 ? void 0 : data.value) !== null && _data$value !== void 0 ? _data$value : data;
422
+ const txResult = (_ref = (_value$TxResult = value === null || value === void 0 ? void 0 : value.TxResult) !== null && _value$TxResult !== void 0 ? _value$TxResult : value === null || value === void 0 ? void 0 : value.tx_result) !== null && _ref !== void 0 ? _ref : value;
423
+ const result = (_txResult$result = txResult === null || txResult === void 0 ? void 0 : txResult.result) !== null && _txResult$result !== void 0 ? _txResult$result : txResult === null || txResult === void 0 ? void 0 : txResult.Result;
424
+ if (!txResult || !result) return;
425
+ return {
426
+ txHash,
427
+ logs: [],
428
+ timestamp: "",
429
+ data: result.data || "",
430
+ info: result.info || "",
431
+ events: result.events || [],
432
+ code: Number(result.code || 0),
433
+ codespace: result.codespace || "",
434
+ rawLog: result.log || result.raw_log || "",
435
+ height: Number(txResult.height || (value === null || value === void 0 ? void 0 : value.height) || 0),
436
+ gasUsed: Number(result.gas_used || result.gasUsed || 0),
437
+ gasWanted: Number(result.gas_wanted || result.gasWanted || 0)
438
+ };
439
+ }
440
+ function readTxEventHashes(data) {
441
+ var _data$events$txHash, _data$events, _data$events2;
442
+ const txHashEvent = (_data$events$txHash = data === null || data === void 0 || (_data$events = data.events) === null || _data$events === void 0 ? void 0 : _data$events["tx.hash"]) !== null && _data$events$txHash !== void 0 ? _data$events$txHash : data === null || data === void 0 || (_data$events2 = data.events) === null || _data$events2 === void 0 ? void 0 : _data$events2.tx_hash;
443
+ if (Array.isArray(txHashEvent)) return txHashEvent.map(String);
444
+ if (txHashEvent) return [String(txHashEvent)];
445
+ return [];
446
+ }
447
+
448
+ //#endregion
449
+ //#region src/core/tx/api/TxInclusion.ts
450
+ function isTendermintEventStrategy(inclusionStrategy) {
451
+ return inclusionStrategy === TxInclusionStrategy.TendermintEvent || inclusionStrategy === TxInclusionStrategy.TendermintEventAndPoll;
452
+ }
453
+ async function prepareTxInclusionWaiter({ txHash, timeout, options, fetchTx, fetchTxPoll, createRequestException }) {
454
+ const inclusionStrategy = options === null || options === void 0 ? void 0 : options.inclusionStrategy;
455
+ if (!isTendermintEventStrategy(inclusionStrategy)) return createPollingInclusionWaiter({
456
+ txHash,
457
+ timeout,
458
+ options,
459
+ fetchTxPoll
460
+ });
461
+ const eventOptions = options === null || options === void 0 ? void 0 : options.eventInclusion;
462
+ const rpcEndpoint = eventOptions === null || eventOptions === void 0 ? void 0 : eventOptions.rpcEndpoint;
463
+ const fallbackToPolling = (eventOptions === null || eventOptions === void 0 ? void 0 : eventOptions.fallbackToPolling) !== false;
464
+ if (!rpcEndpoint) {
465
+ var _eventOptions$onFallb;
466
+ const error = new __injectivelabs_exceptions.GeneralException(/* @__PURE__ */ new Error("Tendermint RPC endpoint is required for event inclusion"));
467
+ if (!fallbackToPolling) throw createRequestException(error, "event-inclusion");
468
+ eventOptions === null || eventOptions === void 0 || (_eventOptions$onFallb = eventOptions.onFallback) === null || _eventOptions$onFallb === void 0 || _eventOptions$onFallb.call(eventOptions, error);
469
+ return createPollingInclusionWaiter({
470
+ txHash,
471
+ timeout,
472
+ options,
473
+ fetchTxPoll
474
+ });
475
+ }
476
+ try {
477
+ const subscription = await subscribeToTendermintTxEvent({
478
+ txHash,
479
+ endpoint: rpcEndpoint,
480
+ timeout: (eventOptions === null || eventOptions === void 0 ? void 0 : eventOptions.timeout) || timeout,
481
+ webSocketFactory: eventOptions === null || eventOptions === void 0 ? void 0 : eventOptions.webSocketFactory
482
+ });
483
+ const hashMismatchPollAbortController = new AbortController();
484
+ const close = () => {
485
+ hashMismatchPollAbortController.abort();
486
+ subscription.close();
487
+ };
488
+ return {
489
+ txHash,
490
+ inclusionStrategy,
491
+ close,
492
+ wait: async (includedTxHash = txHash) => {
493
+ if (includedTxHash.toUpperCase() !== txHash.toUpperCase()) {
494
+ var _eventOptions$onFallb2;
495
+ subscription.close();
496
+ eventOptions === null || eventOptions === void 0 || (_eventOptions$onFallb2 = eventOptions.onFallback) === null || _eventOptions$onFallb2 === void 0 || _eventOptions$onFallb2.call(eventOptions, new __injectivelabs_exceptions.GeneralException(/* @__PURE__ */ new Error(`Broadcast tx hash ${includedTxHash} did not match subscribed tx hash ${txHash}`)));
497
+ return fetchTxPoll(createFetchTxPollArgs({
498
+ txHash: includedTxHash,
499
+ timeout,
500
+ options,
501
+ abortSignal: hashMismatchPollAbortController.signal
502
+ }));
503
+ }
504
+ if (inclusionStrategy === TxInclusionStrategy.TendermintEventAndPoll) return waitForSubscribedTxInclusionAndPoll({
505
+ txHash,
506
+ timeout,
507
+ fetchTx,
508
+ options,
509
+ fetchTxPoll,
510
+ subscription
511
+ });
512
+ return waitForSubscribedTxInclusion({
513
+ txHash,
514
+ timeout,
515
+ options,
516
+ fetchTx,
517
+ subscription,
518
+ fetchTxPoll,
519
+ createRequestException
520
+ });
521
+ }
522
+ };
523
+ } catch (e) {
524
+ var _eventOptions$onFallb3;
525
+ if (e instanceof __injectivelabs_exceptions.TransactionException) throw e;
526
+ const error = e instanceof Error ? e : new Error(String(e));
527
+ if (!fallbackToPolling) throw createRequestException(error, "event-inclusion");
528
+ eventOptions === null || eventOptions === void 0 || (_eventOptions$onFallb3 = eventOptions.onFallback) === null || _eventOptions$onFallb3 === void 0 || _eventOptions$onFallb3.call(eventOptions, error);
529
+ return createPollingInclusionWaiter({
530
+ txHash,
531
+ timeout,
532
+ options,
533
+ fetchTxPoll
534
+ });
535
+ }
536
+ }
537
+ function createPollingInclusionWaiter({ txHash, timeout, options, fetchTxPoll }) {
538
+ const pollAbortController = new AbortController();
539
+ return {
540
+ txHash,
541
+ inclusionStrategy: TxInclusionStrategy.Poll,
542
+ close: () => {
543
+ pollAbortController.abort();
544
+ },
545
+ wait: (includedTxHash = txHash) => fetchTxPoll(createFetchTxPollArgs({
546
+ txHash: includedTxHash,
547
+ timeout,
548
+ options,
549
+ abortSignal: pollAbortController.signal
550
+ }))
551
+ };
552
+ }
553
+ function createFetchTxPollArgs({ txHash, timeout, options, abortSignal }) {
554
+ return {
555
+ ...(options === null || options === void 0 ? void 0 : options.pollingInterval) === void 0 ? {} : { pollingInterval: options.pollingInterval },
556
+ ...abortSignal ? { abortSignal } : {},
557
+ txHash,
558
+ timeout
559
+ };
560
+ }
561
+ async function waitForSubscribedTxInclusion({ txHash, timeout, options, fetchTx, fetchTxPoll, subscription, createRequestException }) {
562
+ var _options$eventInclusi;
563
+ const fallbackToPolling = (options === null || options === void 0 || (_options$eventInclusi = options.eventInclusion) === null || _options$eventInclusi === void 0 ? void 0 : _options$eventInclusi.fallbackToPolling) !== false;
564
+ try {
565
+ return await waitForSubscribedTxEvent({
566
+ txHash,
567
+ subscription,
568
+ fetchTx
569
+ });
570
+ } catch (e) {
571
+ var _options$eventInclusi2, _options$eventInclusi3;
572
+ if (e instanceof __injectivelabs_exceptions.TransactionException) throw e;
573
+ const error = e instanceof __injectivelabs_exceptions.GeneralException ? e : new __injectivelabs_exceptions.GeneralException(new Error(String(e)));
574
+ if (!fallbackToPolling) throw createRequestException(error, "event-inclusion");
575
+ options === null || options === void 0 || (_options$eventInclusi2 = options.eventInclusion) === null || _options$eventInclusi2 === void 0 || (_options$eventInclusi3 = _options$eventInclusi2.onFallback) === null || _options$eventInclusi3 === void 0 || _options$eventInclusi3.call(_options$eventInclusi2, error);
576
+ return fetchTxPoll(createFetchTxPollArgs({
577
+ txHash,
578
+ timeout,
579
+ options
580
+ }));
581
+ }
582
+ }
583
+ async function waitForSubscribedTxInclusionAndPoll({ txHash, timeout, options, fetchTx, fetchTxPoll, subscription }) {
584
+ const pollAbortController = new AbortController();
585
+ return new Promise((resolve, reject) => {
586
+ let settled = false;
587
+ let finishedCount = 0;
588
+ let eventError;
589
+ let pollError;
590
+ const rejectIfBothFailed = () => {
591
+ if (finishedCount < 2 || settled) return;
592
+ reject(pollError || eventError || new __injectivelabs_exceptions.GeneralException(/* @__PURE__ */ new Error("Tx inclusion failed")));
593
+ };
594
+ const resolveOnce = (txResponse, source) => {
595
+ if (settled) return;
596
+ settled = true;
597
+ if (source === "poll") {
598
+ subscription.close();
599
+ resolve(txResponse);
600
+ return;
601
+ }
602
+ pollAbortController.abort();
603
+ resolve(txResponse);
604
+ };
605
+ const rejectTerminal = (error) => {
606
+ if (settled) return true;
607
+ if (error instanceof __injectivelabs_exceptions.TransactionException) {
608
+ settled = true;
609
+ subscription.close();
610
+ pollAbortController.abort();
611
+ reject(error);
612
+ return true;
613
+ }
614
+ return false;
615
+ };
616
+ waitForSubscribedTxEvent({
617
+ txHash,
618
+ subscription,
619
+ fetchTx
620
+ }).then((txResponse) => resolveOnce(txResponse, "event")).catch((error) => {
621
+ var _options$eventInclusi4, _options$eventInclusi5;
622
+ if (rejectTerminal(error)) return;
623
+ const fallbackError = error instanceof Error ? error : new Error(String(error));
624
+ eventError = fallbackError;
625
+ finishedCount += 1;
626
+ options === null || options === void 0 || (_options$eventInclusi4 = options.eventInclusion) === null || _options$eventInclusi4 === void 0 || (_options$eventInclusi5 = _options$eventInclusi4.onFallback) === null || _options$eventInclusi5 === void 0 || _options$eventInclusi5.call(_options$eventInclusi4, fallbackError);
627
+ rejectIfBothFailed();
628
+ });
629
+ fetchTxPoll(createFetchTxPollArgs({
630
+ txHash,
631
+ timeout,
632
+ options,
633
+ abortSignal: pollAbortController.signal
634
+ })).then((txResponse) => resolveOnce(txResponse, "poll")).catch((error) => {
635
+ if (rejectTerminal(error)) return;
636
+ pollError = error instanceof Error ? error : new Error(String(error));
637
+ finishedCount += 1;
638
+ rejectIfBothFailed();
639
+ });
640
+ });
641
+ }
642
+ async function waitForSubscribedTxEvent({ txHash, fetchTx, subscription }) {
643
+ const eventTx = await subscription.wait();
644
+ if (eventTx.code !== 0) throw new __injectivelabs_exceptions.TransactionException(new Error(eventTx.rawLog), {
645
+ contextCode: eventTx.code,
646
+ contextModule: eventTx.codespace
647
+ });
648
+ return fetchTx(txHash);
649
+ }
650
+
265
651
  //#endregion
266
652
  //#region src/core/tx/api/TxGrpcApi.ts
267
653
  var TxGrpcApi = class extends require_BaseGrpcConsumer.BaseGrpcConsumer {
@@ -301,16 +687,24 @@ var TxGrpcApi = class extends require_BaseGrpcConsumer.BaseGrpcConsumer {
301
687
  });
302
688
  }
303
689
  }
304
- async fetchTxPoll(txHash, timeout = __injectivelabs_utils.DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS) {
690
+ async fetchTxPoll({ txHash, abortSignal, timeout = __injectivelabs_utils.DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS, pollingInterval = __injectivelabs_utils.DEFAULT_TX_POLL_INTERVAL_MS }) {
305
691
  const deadline = Date.now() + timeout;
306
692
  for (let start = Date.now(); start < deadline; start = Date.now()) {
693
+ this.throwIfTxPollingCancelled(abortSignal);
307
694
  try {
308
- const tx = await this.fetchTxDual(txHash, deadline);
695
+ const tx = await this.fetchTxDual({
696
+ txHash,
697
+ deadline,
698
+ abortSignal
699
+ });
700
+ this.throwIfTxPollingCancelled(abortSignal);
309
701
  if (tx) return tx;
310
702
  } catch (e) {
703
+ this.throwIfTxPollingCancelled(abortSignal);
311
704
  if (e instanceof __injectivelabs_exceptions.TransactionException) throw e;
312
705
  }
313
- const gap = __injectivelabs_utils.DEFAULT_TX_POLL_INTERVAL_MS - (Date.now() - start);
706
+ this.throwIfTxPollingCancelled(abortSignal);
707
+ const gap = pollingInterval - (Date.now() - start);
314
708
  if (gap > 0) await (0, __injectivelabs_utils.sleep)(gap);
315
709
  }
316
710
  throw new __injectivelabs_exceptions.GrpcUnaryRequestException(/* @__PURE__ */ new Error(`Transaction was not included in a block before timeout of ${timeout}ms`), {
@@ -318,20 +712,57 @@ var TxGrpcApi = class extends require_BaseGrpcConsumer.BaseGrpcConsumer {
318
712
  contextModule: "fetch-tx-poll"
319
713
  });
320
714
  }
321
- async safeFetchTx(txHash, delay) {
715
+ async waitForTxInclusion({ txHash, timeout = __injectivelabs_utils.DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS, options }) {
716
+ const txResponse = await (await this.prepareTxInclusionWait({
717
+ txHash,
718
+ timeout,
719
+ options
720
+ })).wait();
721
+ if (!txResponse) throw new __injectivelabs_exceptions.GrpcUnaryRequestException(/* @__PURE__ */ new Error(`The transaction with ${txHash} is not found`), {
722
+ context: "TxGrpcApi",
723
+ contextModule: "wait-for-tx-inclusion"
724
+ });
725
+ return txResponse;
726
+ }
727
+ async prepareTxInclusionWait({ txHash, timeout = __injectivelabs_utils.DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS, options }) {
728
+ return prepareTxInclusionWaiter({
729
+ txHash,
730
+ timeout,
731
+ options,
732
+ fetchTx: (includedTxHash) => this.fetchTx(includedTxHash),
733
+ fetchTxPoll: (args) => this.fetchTxPoll(args),
734
+ createRequestException: (error, contextModule) => new __injectivelabs_exceptions.GrpcUnaryRequestException(error, {
735
+ context: "TxGrpcApi",
736
+ contextModule
737
+ })
738
+ });
739
+ }
740
+ async safeFetchTx({ txHash, delay, abortSignal }) {
322
741
  if (delay) await (0, __injectivelabs_utils.sleep)(delay);
742
+ this.throwIfTxPollingCancelled(abortSignal);
323
743
  return this.fetchTx(txHash).catch((e) => {
324
744
  if (e instanceof __injectivelabs_exceptions.TransactionException) throw e;
325
745
  return null;
326
746
  });
327
747
  }
328
- fetchTxDual(txHash, deadline) {
748
+ fetchTxDual({ txHash, deadline, abortSignal }) {
329
749
  const STAGGER = 300;
330
750
  const timeout = Math.max(0, Math.min(__injectivelabs_utils.DEFAULT_TX_POLL_CALL_TIMEOUT_MS, deadline - Date.now()));
331
- const fetches = Promise.all([this.safeFetchTx(txHash), this.safeFetchTx(txHash, STAGGER)]).then(([a, b]) => a !== null && a !== void 0 ? a : b);
751
+ const fetches = Promise.all([this.safeFetchTx({
752
+ txHash,
753
+ abortSignal
754
+ }), this.safeFetchTx({
755
+ txHash,
756
+ delay: STAGGER,
757
+ abortSignal
758
+ })]).then(([a, b]) => a !== null && a !== void 0 ? a : b);
332
759
  fetches.catch(() => {});
333
760
  return Promise.race([fetches, (0, __injectivelabs_utils.sleep)(timeout).then(() => null)]);
334
761
  }
762
+ throwIfTxPollingCancelled(abortSignal) {
763
+ if (!(abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted)) return;
764
+ throw new Error("Transaction inclusion polling was cancelled");
765
+ }
335
766
  async simulate(txRaw) {
336
767
  const txRawClone = __injectivelabs_core_proto_ts_v2_generated_cosmos_tx_v1beta1_tx_pb.TxRaw.create({ ...txRaw });
337
768
  const simulateRequest = __injectivelabs_core_proto_ts_v2_generated_cosmos_tx_v1beta1_service_pb.SimulateRequest.create();
@@ -361,12 +792,19 @@ var TxGrpcApi = class extends require_BaseGrpcConsumer.BaseGrpcConsumer {
361
792
  }
362
793
  }
363
794
  async broadcast(txRaw, options) {
364
- const mode = (options === null || options === void 0 ? void 0 : options.mode) || __injectivelabs_core_proto_ts_v2_generated_cosmos_tx_v1beta1_service_pb.BroadcastMode.SYNC;
365
795
  const timeout = (options === null || options === void 0 ? void 0 : options.timeout) || (0, __injectivelabs_utils.toBigNumber)((options === null || options === void 0 ? void 0 : options.txTimeout) || __injectivelabs_utils.DEFAULT_BLOCK_TIMEOUT_HEIGHT).times(__injectivelabs_utils.DEFAULT_BLOCK_TIME_IN_SECONDS * 1e3).toNumber();
366
- const broadcastTxRequest = __injectivelabs_core_proto_ts_v2_generated_cosmos_tx_v1beta1_service_pb.BroadcastTxRequest.create();
367
- broadcastTxRequest.txBytes = __injectivelabs_core_proto_ts_v2_generated_cosmos_tx_v1beta1_tx_pb.TxRaw.toBinary(txRaw);
368
- broadcastTxRequest.mode = mode;
796
+ const txHash = TxClient.hash(txRaw);
797
+ let inclusionWaiter;
369
798
  try {
799
+ inclusionWaiter = await this.prepareTxInclusionWait({
800
+ txHash,
801
+ timeout,
802
+ options
803
+ });
804
+ const mode = (options === null || options === void 0 ? void 0 : options.mode) || (inclusionWaiter.inclusionStrategy !== TxInclusionStrategy.Poll ? __injectivelabs_core_proto_ts_v2_generated_cosmos_tx_v1beta1_service_pb.BroadcastMode.ASYNC : __injectivelabs_core_proto_ts_v2_generated_cosmos_tx_v1beta1_service_pb.BroadcastMode.SYNC);
805
+ const broadcastTxRequest = __injectivelabs_core_proto_ts_v2_generated_cosmos_tx_v1beta1_service_pb.BroadcastTxRequest.create();
806
+ broadcastTxRequest.txBytes = __injectivelabs_core_proto_ts_v2_generated_cosmos_tx_v1beta1_tx_pb.TxRaw.toBinary(txRaw);
807
+ broadcastTxRequest.mode = mode;
370
808
  const txResponse = (await this.executeGrpcCall(broadcastTxRequest, this.client.broadcastTx.bind(this.client))).txResponse;
371
809
  if (!txResponse) throw new __injectivelabs_exceptions.GrpcUnaryRequestException(/* @__PURE__ */ new Error(`The transaction has failed to be broadcasted`), {
372
810
  context: "TxGrpcApi.broadcast",
@@ -377,8 +815,14 @@ var TxGrpcApi = class extends require_BaseGrpcConsumer.BaseGrpcConsumer {
377
815
  contextModule: txResponse.codespace
378
816
  });
379
817
  if (options === null || options === void 0 ? void 0 : options.onBroadcast) options.onBroadcast(txResponse.txhash);
380
- return await this.fetchTxPoll(txResponse.txhash, timeout);
818
+ const result = await inclusionWaiter.wait(txResponse.txhash);
819
+ if (!result) throw new __injectivelabs_exceptions.GrpcUnaryRequestException(/* @__PURE__ */ new Error(`The transaction with ${txResponse.txhash} is not found`), {
820
+ context: "TxGrpcApi.broadcast",
821
+ contextModule: "wait-for-tx-inclusion"
822
+ });
823
+ return result;
381
824
  } catch (e) {
825
+ inclusionWaiter === null || inclusionWaiter === void 0 || inclusionWaiter.close();
382
826
  if (e instanceof __injectivelabs_exceptions.TransactionException) throw e;
383
827
  if (e instanceof __injectivelabs_exceptions.GrpcUnaryRequestException) throw e;
384
828
  throw new __injectivelabs_exceptions.TransactionException(new Error(e));
@@ -465,17 +909,20 @@ var TxRestApi = class {
465
909
  });
466
910
  }
467
911
  }
468
- async fetchTxPoll(txHash, timeout = __injectivelabs_utils.DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS) {
912
+ async fetchTxPoll({ txHash, timeout = __injectivelabs_utils.DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS, pollingInterval = __injectivelabs_utils.DEFAULT_TX_POLL_INTERVAL_MS, abortSignal }) {
469
913
  const deadline = Date.now() + timeout;
470
914
  for (let start = Date.now(); start < deadline; start = Date.now()) {
915
+ this.throwIfTxPollingCancelled(abortSignal);
471
916
  const callTimeout = Math.max(0, Math.min(__injectivelabs_utils.DEFAULT_TX_POLL_CALL_TIMEOUT_MS, deadline - Date.now()));
472
917
  try {
473
918
  const txResponse = await Promise.race([this.fetchTx(txHash), (0, __injectivelabs_utils.sleep)(callTimeout).then(() => null)]);
474
919
  if (txResponse) return txResponse;
475
920
  } catch (e) {
921
+ this.throwIfTxPollingCancelled(abortSignal);
476
922
  if (e instanceof __injectivelabs_exceptions.TransactionException) throw e;
477
923
  }
478
- const remaining = __injectivelabs_utils.DEFAULT_TX_POLL_INTERVAL_MS - (Date.now() - start);
924
+ this.throwIfTxPollingCancelled(abortSignal);
925
+ const remaining = pollingInterval - (Date.now() - start);
479
926
  if (remaining > 0) await (0, __injectivelabs_utils.sleep)(remaining);
480
927
  }
481
928
  throw new __injectivelabs_exceptions.HttpRequestException(/* @__PURE__ */ new Error(`Transaction was not included in a block before timeout of ${timeout}ms`), {
@@ -483,6 +930,35 @@ var TxRestApi = class {
483
930
  contextModule: "TxRestApi.fetch-tx-poll"
484
931
  });
485
932
  }
933
+ throwIfTxPollingCancelled(abortSignal) {
934
+ if (!(abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted)) return;
935
+ throw new Error("Transaction inclusion polling was cancelled");
936
+ }
937
+ async waitForTxInclusion({ txHash, timeout = __injectivelabs_utils.DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS, options }) {
938
+ const txResponse = await (await this.prepareTxInclusionWait({
939
+ txHash,
940
+ timeout,
941
+ options
942
+ })).wait();
943
+ if (!txResponse) throw new __injectivelabs_exceptions.HttpRequestException(/* @__PURE__ */ new Error(`The transaction with ${txHash} is not found`), {
944
+ context: "TxRestApi",
945
+ contextModule: "wait-for-tx-inclusion"
946
+ });
947
+ return txResponse;
948
+ }
949
+ async prepareTxInclusionWait({ txHash, timeout = __injectivelabs_utils.DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS, options }) {
950
+ return prepareTxInclusionWaiter({
951
+ txHash,
952
+ timeout,
953
+ options,
954
+ fetchTx: (includedTxHash) => this.fetchTx(includedTxHash),
955
+ fetchTxPoll: (args) => this.fetchTxPoll(args),
956
+ createRequestException: (error, contextModule) => new __injectivelabs_exceptions.HttpRequestException(error, {
957
+ context: "TxRestApi",
958
+ contextModule
959
+ })
960
+ });
961
+ }
486
962
  async simulate(txRaw) {
487
963
  const txRawClone = __injectivelabs_core_proto_ts_v2_generated_cosmos_tx_v1beta1_tx_pb.TxRaw.create({ ...txRaw });
488
964
  if (txRawClone.signatures.length === 0) txRawClone.signatures = [new Uint8Array(0)];
@@ -505,8 +981,15 @@ var TxRestApi = class {
505
981
  }
506
982
  async broadcast(txRaw, options) {
507
983
  const timeout = (options === null || options === void 0 ? void 0 : options.timeout) || (0, __injectivelabs_utils.toBigNumber)((options === null || options === void 0 ? void 0 : options.txTimeout) || __injectivelabs_utils.DEFAULT_BLOCK_TIMEOUT_HEIGHT).times(__injectivelabs_utils.DEFAULT_BLOCK_TIME_IN_SECONDS * 1e3).toNumber();
984
+ const txHash = TxClient.hash(txRaw);
985
+ let inclusionWaiter;
508
986
  try {
509
- const { tx_response: txResponse } = await this.broadcastTx(txRaw, BroadcastMode.Sync);
987
+ inclusionWaiter = await this.prepareTxInclusionWait({
988
+ txHash,
989
+ timeout,
990
+ options
991
+ });
992
+ const { tx_response: txResponse } = await this.broadcastTx(txRaw, inclusionWaiter.inclusionStrategy !== TxInclusionStrategy.Poll ? BroadcastMode.Async : BroadcastMode.Sync);
510
993
  if (!txResponse) throw new __injectivelabs_exceptions.HttpRequestException(/* @__PURE__ */ new Error("The transaction has failed to be broadcasted"), {
511
994
  context: "TxRestApi.broadcast",
512
995
  contextModule: "broadcast"
@@ -516,8 +999,14 @@ var TxRestApi = class {
516
999
  contextModule: txResponse.codespace
517
1000
  });
518
1001
  if (options === null || options === void 0 ? void 0 : options.onBroadcast) options.onBroadcast(txResponse.txhash);
519
- return await this.fetchTxPoll(txResponse.txhash, timeout);
1002
+ const result = await inclusionWaiter.wait(txResponse.txhash);
1003
+ if (!result) throw new __injectivelabs_exceptions.HttpRequestException(/* @__PURE__ */ new Error(`The transaction with ${txResponse.txhash} is not found`), {
1004
+ context: "TxRestApi.broadcast",
1005
+ contextModule: "wait-for-tx-inclusion"
1006
+ });
1007
+ return result;
520
1008
  } catch (e) {
1009
+ inclusionWaiter === null || inclusionWaiter === void 0 || inclusionWaiter.close();
521
1010
  if (e instanceof __injectivelabs_exceptions.HttpRequestException) {
522
1011
  if (e.code !== http_status_codes.StatusCodes.OK) throw e;
523
1012
  }
@@ -610,7 +1099,13 @@ var TxRestApi = class {
610
1099
  //#region src/core/tx/api/utils.ts
611
1100
  const waitTxBroadcasted = (txHash, options) => {
612
1101
  const timeout = (0, __injectivelabs_utils.toBigNumber)((options === null || options === void 0 ? void 0 : options.txTimeout) || __injectivelabs_utils.DEFAULT_BLOCK_TIMEOUT_HEIGHT).times(__injectivelabs_utils.DEFAULT_BLOCK_TIME_IN_SECONDS * 1e3).toNumber();
613
- return options.endpoints.grpc ? new TxGrpcApi(options.endpoints.grpc).fetchTxPoll(txHash, timeout) : new TxRestApi(options.endpoints.rest).fetchTxPoll(txHash, timeout);
1102
+ return options.endpoints.grpc ? new TxGrpcApi(options.endpoints.grpc).fetchTxPoll({
1103
+ txHash,
1104
+ timeout
1105
+ }) : new TxRestApi(options.endpoints.rest).fetchTxPoll({
1106
+ txHash,
1107
+ timeout
1108
+ });
614
1109
  };
615
1110
 
616
1111
  //#endregion
@@ -641,13 +1136,6 @@ const generateArbitrarySignDoc = (message, signer) => {
641
1136
  };
642
1137
  };
643
1138
 
644
- //#endregion
645
- //#region src/core/tx/types/tx.ts
646
- const TxClientMode = {
647
- gRpc: "grpc",
648
- rest: "rest"
649
- };
650
-
651
1139
  //#endregion
652
1140
  //#region src/core/tx/broadcaster/MsgBroadcasterWithPk.ts
653
1141
  /**
@@ -737,7 +1225,11 @@ var MsgBroadcasterWithPk = class {
737
1225
  chainId: evmChainId,
738
1226
  signature: `0x${require_utils.uint8ArrayToHex(signature)}`
739
1227
  });
740
- return await new TxGrpcApi(endpoints.grpc).fetchTxPoll(response.txHash);
1228
+ const timeoutInMs = (0, __injectivelabs_utils.toBigNumber)(txTimeout).times(__injectivelabs_utils.DEFAULT_BLOCK_TIME_IN_SECONDS).times(1e3).toNumber();
1229
+ return await new TxGrpcApi(endpoints.grpc).fetchTxPoll({
1230
+ txHash: response.txHash,
1231
+ timeout: timeoutInMs
1232
+ });
741
1233
  }
742
1234
  /**
743
1235
  * Broadcasting the transaction using the client
@@ -952,6 +1444,12 @@ Object.defineProperty(exports, 'TxGrpcApi', {
952
1444
  return TxGrpcApi;
953
1445
  }
954
1446
  });
1447
+ Object.defineProperty(exports, 'TxInclusionStrategy', {
1448
+ enumerable: true,
1449
+ get: function () {
1450
+ return TxInclusionStrategy;
1451
+ }
1452
+ });
955
1453
  Object.defineProperty(exports, 'TxRestApi', {
956
1454
  enumerable: true,
957
1455
  get: function () {
@@ -1024,6 +1522,18 @@ Object.defineProperty(exports, 'isTxNotFoundError', {
1024
1522
  return isTxNotFoundError;
1025
1523
  }
1026
1524
  });
1525
+ Object.defineProperty(exports, 'normalizeTendermintWebSocketEndpoint', {
1526
+ enumerable: true,
1527
+ get: function () {
1528
+ return normalizeTendermintWebSocketEndpoint;
1529
+ }
1530
+ });
1531
+ Object.defineProperty(exports, 'subscribeToTendermintTxEvent', {
1532
+ enumerable: true,
1533
+ get: function () {
1534
+ return subscribeToTendermintTxEvent;
1535
+ }
1536
+ });
1027
1537
  Object.defineProperty(exports, 'waitTxBroadcasted', {
1028
1538
  enumerable: true,
1029
1539
  get: function () {