@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.
@@ -257,6 +257,392 @@ const getTxRawFromTxRawOrDirectSignResponse = (txRawOrDirectSignResponse) => {
257
257
  return txRawOrDirectSignResponse.signed === void 0 ? txRawOrDirectSignResponse : createTxRawFromSigResponse(txRawOrDirectSignResponse);
258
258
  };
259
259
 
260
+ //#endregion
261
+ //#region src/core/tx/types/tx.ts
262
+ const TxInclusionStrategy = {
263
+ Poll: "poll",
264
+ TendermintEvent: "tendermint-event",
265
+ TendermintEventAndPoll: "tendermint-event-and-poll"
266
+ };
267
+ const TxClientMode = {
268
+ gRpc: "grpc",
269
+ rest: "rest"
270
+ };
271
+
272
+ //#endregion
273
+ //#region src/core/tx/api/TxEventInclusion.ts
274
+ function normalizeTendermintWebSocketEndpoint(endpoint) {
275
+ let normalized = endpoint;
276
+ if (normalized.startsWith("http://")) normalized = `ws://${normalized.slice(7)}`;
277
+ else if (normalized.startsWith("https://")) normalized = `wss://${normalized.slice(8)}`;
278
+ return normalized.endsWith("/websocket") ? normalized : `${normalized.replace(/\/$/, "")}/websocket`;
279
+ }
280
+ async function subscribeToTendermintTxEvent({ txHash, timeout, endpoint, webSocketFactory }) {
281
+ const normalizedTxHash = normalizeTendermintTxHash(txHash);
282
+ const socket = createTendermintSocket(normalizeTendermintWebSocketEndpoint(endpoint), webSocketFactory);
283
+ const query = `tm.event='Tx' AND tx.hash='${normalizedTxHash}'`;
284
+ const requestId = `tx-event-${Date.now()}-${Math.random()}`;
285
+ return new Promise((resolve, reject) => {
286
+ let ready = false;
287
+ let waitSettled = false;
288
+ let closedIntentionally = false;
289
+ let timeoutId;
290
+ let waitResolve;
291
+ let waitReject;
292
+ const waitPromise = new Promise((resolveWait$1, rejectWait$1) => {
293
+ waitResolve = resolveWait$1;
294
+ waitReject = rejectWait$1;
295
+ });
296
+ const resolveSubscription = () => {
297
+ if (ready) return;
298
+ ready = true;
299
+ resolve({
300
+ close: cleanup,
301
+ wait: () => waitPromise
302
+ });
303
+ };
304
+ const cleanup = () => {
305
+ closedIntentionally = true;
306
+ clearTimeout(timeoutId);
307
+ socket.removeEventListener("open", onOpen);
308
+ socket.removeEventListener("message", onMessage);
309
+ socket.removeEventListener("error", onError);
310
+ socket.removeEventListener("close", onClose);
311
+ if (socket.readyState === 1 || socket.readyState === 0) socket.close();
312
+ };
313
+ const rejectWait = (error) => {
314
+ if (waitSettled) return;
315
+ waitSettled = true;
316
+ waitReject(error);
317
+ cleanup();
318
+ };
319
+ timeoutId = setTimeout(() => {
320
+ const error = /* @__PURE__ */ new Error(`Timed out waiting for Tendermint tx event after ${timeout}ms`);
321
+ if (ready) {
322
+ rejectWait(error);
323
+ return;
324
+ }
325
+ cleanup();
326
+ reject(error);
327
+ }, timeout);
328
+ const resolveWait = (response) => {
329
+ if (waitSettled) return;
330
+ waitSettled = true;
331
+ waitResolve(response);
332
+ cleanup();
333
+ };
334
+ const rejectForMessageError = (error) => {
335
+ if (ready) {
336
+ rejectWait(error);
337
+ return;
338
+ }
339
+ cleanup();
340
+ reject(error);
341
+ };
342
+ const onOpen = () => {
343
+ socket.send(JSON.stringify({
344
+ id: requestId,
345
+ jsonrpc: "2.0",
346
+ method: "subscribe",
347
+ params: { query }
348
+ }));
349
+ };
350
+ const onMessage = (event) => {
351
+ readMessageEventData(event).then((messageData) => {
352
+ const message = JSON.parse(messageData);
353
+ const eventResponse = parseTxEventResponse(message, normalizedTxHash);
354
+ if (eventResponse) {
355
+ resolveSubscription();
356
+ resolveWait(eventResponse);
357
+ return;
358
+ }
359
+ if (message.id !== requestId) return;
360
+ if (message.error) {
361
+ rejectForMessageError(/* @__PURE__ */ new Error(`Tendermint subscribe failed: ${JSON.stringify(message.error)}`));
362
+ return;
363
+ }
364
+ resolveSubscription();
365
+ }).catch((error) => {
366
+ rejectForMessageError(error instanceof Error ? error : /* @__PURE__ */ new Error(`Invalid Tendermint WebSocket JSON: ${String(error)}`));
367
+ });
368
+ };
369
+ const onError = () => {
370
+ const error = /* @__PURE__ */ new Error("Tendermint WebSocket error");
371
+ if (ready) {
372
+ rejectWait(error);
373
+ return;
374
+ }
375
+ cleanup();
376
+ reject(error);
377
+ };
378
+ const onClose = () => {
379
+ if (closedIntentionally) return;
380
+ const error = /* @__PURE__ */ new Error("Tendermint WebSocket closed");
381
+ if (ready) {
382
+ rejectWait(error);
383
+ return;
384
+ }
385
+ cleanup();
386
+ reject(error);
387
+ };
388
+ socket.addEventListener("open", onOpen);
389
+ socket.addEventListener("message", onMessage);
390
+ socket.addEventListener("error", onError);
391
+ socket.addEventListener("close", onClose);
392
+ });
393
+ }
394
+ function normalizeTendermintTxHash(txHash) {
395
+ if (!/^[0-9a-fA-F]{64}$/.test(txHash)) throw new Error("Invalid Tendermint tx hash");
396
+ return txHash.toUpperCase();
397
+ }
398
+ function createTendermintSocket(endpoint, webSocketFactory) {
399
+ if (webSocketFactory) return webSocketFactory(endpoint);
400
+ if (!globalThis.WebSocket) throw new Error("WebSocket is not available in this environment");
401
+ return new globalThis.WebSocket(endpoint);
402
+ }
403
+ async function readMessageEventData(event) {
404
+ const { data } = event;
405
+ if (typeof data === "string") return data;
406
+ if (typeof Blob !== "undefined" && data instanceof Blob) return data.text();
407
+ if (typeof ArrayBuffer !== "undefined" && data instanceof ArrayBuffer) return new TextDecoder().decode(data);
408
+ if (ArrayBuffer.isView(data)) return new TextDecoder().decode(data);
409
+ return String(data);
410
+ }
411
+ function parseTxEventResponse(message, txHash) {
412
+ var _message$params$resul, _message$params, _message$result, _data$value, _ref, _value$TxResult, _txResult$result;
413
+ 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;
414
+ const eventTxHashes = readTxEventHashes(data);
415
+ if (eventTxHashes.length > 0 && !eventTxHashes.some((eventTxHash) => eventTxHash.toUpperCase() === txHash.toUpperCase())) return;
416
+ const value = (_data$value = data === null || data === void 0 ? void 0 : data.value) !== null && _data$value !== void 0 ? _data$value : data;
417
+ 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;
418
+ 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;
419
+ if (!txResult || !result) return;
420
+ return {
421
+ txHash,
422
+ logs: [],
423
+ timestamp: "",
424
+ data: result.data || "",
425
+ info: result.info || "",
426
+ events: result.events || [],
427
+ code: Number(result.code || 0),
428
+ codespace: result.codespace || "",
429
+ rawLog: result.log || result.raw_log || "",
430
+ height: Number(txResult.height || (value === null || value === void 0 ? void 0 : value.height) || 0),
431
+ gasUsed: Number(result.gas_used || result.gasUsed || 0),
432
+ gasWanted: Number(result.gas_wanted || result.gasWanted || 0)
433
+ };
434
+ }
435
+ function readTxEventHashes(data) {
436
+ var _data$events$txHash, _data$events, _data$events2;
437
+ 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;
438
+ if (Array.isArray(txHashEvent)) return txHashEvent.map(String);
439
+ if (txHashEvent) return [String(txHashEvent)];
440
+ return [];
441
+ }
442
+
443
+ //#endregion
444
+ //#region src/core/tx/api/TxInclusion.ts
445
+ function isTendermintEventStrategy(inclusionStrategy) {
446
+ return inclusionStrategy === TxInclusionStrategy.TendermintEvent || inclusionStrategy === TxInclusionStrategy.TendermintEventAndPoll;
447
+ }
448
+ async function prepareTxInclusionWaiter({ txHash, timeout, options, fetchTx, fetchTxPoll, createRequestException }) {
449
+ const inclusionStrategy = options === null || options === void 0 ? void 0 : options.inclusionStrategy;
450
+ if (!isTendermintEventStrategy(inclusionStrategy)) return createPollingInclusionWaiter({
451
+ txHash,
452
+ timeout,
453
+ options,
454
+ fetchTxPoll
455
+ });
456
+ const eventOptions = options === null || options === void 0 ? void 0 : options.eventInclusion;
457
+ const rpcEndpoint = eventOptions === null || eventOptions === void 0 ? void 0 : eventOptions.rpcEndpoint;
458
+ const fallbackToPolling = (eventOptions === null || eventOptions === void 0 ? void 0 : eventOptions.fallbackToPolling) !== false;
459
+ if (!rpcEndpoint) {
460
+ var _eventOptions$onFallb;
461
+ const error = new GeneralException(/* @__PURE__ */ new Error("Tendermint RPC endpoint is required for event inclusion"));
462
+ if (!fallbackToPolling) throw createRequestException(error, "event-inclusion");
463
+ eventOptions === null || eventOptions === void 0 || (_eventOptions$onFallb = eventOptions.onFallback) === null || _eventOptions$onFallb === void 0 || _eventOptions$onFallb.call(eventOptions, error);
464
+ return createPollingInclusionWaiter({
465
+ txHash,
466
+ timeout,
467
+ options,
468
+ fetchTxPoll
469
+ });
470
+ }
471
+ try {
472
+ const subscription = await subscribeToTendermintTxEvent({
473
+ txHash,
474
+ endpoint: rpcEndpoint,
475
+ timeout: (eventOptions === null || eventOptions === void 0 ? void 0 : eventOptions.timeout) || timeout,
476
+ webSocketFactory: eventOptions === null || eventOptions === void 0 ? void 0 : eventOptions.webSocketFactory
477
+ });
478
+ const hashMismatchPollAbortController = new AbortController();
479
+ const close = () => {
480
+ hashMismatchPollAbortController.abort();
481
+ subscription.close();
482
+ };
483
+ return {
484
+ txHash,
485
+ inclusionStrategy,
486
+ close,
487
+ wait: async (includedTxHash = txHash) => {
488
+ if (includedTxHash.toUpperCase() !== txHash.toUpperCase()) {
489
+ var _eventOptions$onFallb2;
490
+ subscription.close();
491
+ eventOptions === null || eventOptions === void 0 || (_eventOptions$onFallb2 = eventOptions.onFallback) === null || _eventOptions$onFallb2 === void 0 || _eventOptions$onFallb2.call(eventOptions, new GeneralException(/* @__PURE__ */ new Error(`Broadcast tx hash ${includedTxHash} did not match subscribed tx hash ${txHash}`)));
492
+ return fetchTxPoll(createFetchTxPollArgs({
493
+ txHash: includedTxHash,
494
+ timeout,
495
+ options,
496
+ abortSignal: hashMismatchPollAbortController.signal
497
+ }));
498
+ }
499
+ if (inclusionStrategy === TxInclusionStrategy.TendermintEventAndPoll) return waitForSubscribedTxInclusionAndPoll({
500
+ txHash,
501
+ timeout,
502
+ fetchTx,
503
+ options,
504
+ fetchTxPoll,
505
+ subscription
506
+ });
507
+ return waitForSubscribedTxInclusion({
508
+ txHash,
509
+ timeout,
510
+ options,
511
+ fetchTx,
512
+ subscription,
513
+ fetchTxPoll,
514
+ createRequestException
515
+ });
516
+ }
517
+ };
518
+ } catch (e) {
519
+ var _eventOptions$onFallb3;
520
+ if (e instanceof TransactionException) throw e;
521
+ const error = e instanceof Error ? e : new Error(String(e));
522
+ if (!fallbackToPolling) throw createRequestException(error, "event-inclusion");
523
+ eventOptions === null || eventOptions === void 0 || (_eventOptions$onFallb3 = eventOptions.onFallback) === null || _eventOptions$onFallb3 === void 0 || _eventOptions$onFallb3.call(eventOptions, error);
524
+ return createPollingInclusionWaiter({
525
+ txHash,
526
+ timeout,
527
+ options,
528
+ fetchTxPoll
529
+ });
530
+ }
531
+ }
532
+ function createPollingInclusionWaiter({ txHash, timeout, options, fetchTxPoll }) {
533
+ const pollAbortController = new AbortController();
534
+ return {
535
+ txHash,
536
+ inclusionStrategy: TxInclusionStrategy.Poll,
537
+ close: () => {
538
+ pollAbortController.abort();
539
+ },
540
+ wait: (includedTxHash = txHash) => fetchTxPoll(createFetchTxPollArgs({
541
+ txHash: includedTxHash,
542
+ timeout,
543
+ options,
544
+ abortSignal: pollAbortController.signal
545
+ }))
546
+ };
547
+ }
548
+ function createFetchTxPollArgs({ txHash, timeout, options, abortSignal }) {
549
+ return {
550
+ ...(options === null || options === void 0 ? void 0 : options.pollingInterval) === void 0 ? {} : { pollingInterval: options.pollingInterval },
551
+ ...abortSignal ? { abortSignal } : {},
552
+ txHash,
553
+ timeout
554
+ };
555
+ }
556
+ async function waitForSubscribedTxInclusion({ txHash, timeout, options, fetchTx, fetchTxPoll, subscription, createRequestException }) {
557
+ var _options$eventInclusi;
558
+ const fallbackToPolling = (options === null || options === void 0 || (_options$eventInclusi = options.eventInclusion) === null || _options$eventInclusi === void 0 ? void 0 : _options$eventInclusi.fallbackToPolling) !== false;
559
+ try {
560
+ return await waitForSubscribedTxEvent({
561
+ txHash,
562
+ subscription,
563
+ fetchTx
564
+ });
565
+ } catch (e) {
566
+ var _options$eventInclusi2, _options$eventInclusi3;
567
+ if (e instanceof TransactionException) throw e;
568
+ const error = e instanceof GeneralException ? e : new GeneralException(new Error(String(e)));
569
+ if (!fallbackToPolling) throw createRequestException(error, "event-inclusion");
570
+ 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);
571
+ return fetchTxPoll(createFetchTxPollArgs({
572
+ txHash,
573
+ timeout,
574
+ options
575
+ }));
576
+ }
577
+ }
578
+ async function waitForSubscribedTxInclusionAndPoll({ txHash, timeout, options, fetchTx, fetchTxPoll, subscription }) {
579
+ const pollAbortController = new AbortController();
580
+ return new Promise((resolve, reject) => {
581
+ let settled = false;
582
+ let finishedCount = 0;
583
+ let eventError;
584
+ let pollError;
585
+ const rejectIfBothFailed = () => {
586
+ if (finishedCount < 2 || settled) return;
587
+ reject(pollError || eventError || new GeneralException(/* @__PURE__ */ new Error("Tx inclusion failed")));
588
+ };
589
+ const resolveOnce = (txResponse, source) => {
590
+ if (settled) return;
591
+ settled = true;
592
+ if (source === "poll") {
593
+ subscription.close();
594
+ resolve(txResponse);
595
+ return;
596
+ }
597
+ pollAbortController.abort();
598
+ resolve(txResponse);
599
+ };
600
+ const rejectTerminal = (error) => {
601
+ if (settled) return true;
602
+ if (error instanceof TransactionException) {
603
+ settled = true;
604
+ subscription.close();
605
+ pollAbortController.abort();
606
+ reject(error);
607
+ return true;
608
+ }
609
+ return false;
610
+ };
611
+ waitForSubscribedTxEvent({
612
+ txHash,
613
+ subscription,
614
+ fetchTx
615
+ }).then((txResponse) => resolveOnce(txResponse, "event")).catch((error) => {
616
+ var _options$eventInclusi4, _options$eventInclusi5;
617
+ if (rejectTerminal(error)) return;
618
+ const fallbackError = error instanceof Error ? error : new Error(String(error));
619
+ eventError = fallbackError;
620
+ finishedCount += 1;
621
+ 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);
622
+ rejectIfBothFailed();
623
+ });
624
+ fetchTxPoll(createFetchTxPollArgs({
625
+ txHash,
626
+ timeout,
627
+ options,
628
+ abortSignal: pollAbortController.signal
629
+ })).then((txResponse) => resolveOnce(txResponse, "poll")).catch((error) => {
630
+ if (rejectTerminal(error)) return;
631
+ pollError = error instanceof Error ? error : new Error(String(error));
632
+ finishedCount += 1;
633
+ rejectIfBothFailed();
634
+ });
635
+ });
636
+ }
637
+ async function waitForSubscribedTxEvent({ txHash, fetchTx, subscription }) {
638
+ const eventTx = await subscription.wait();
639
+ if (eventTx.code !== 0) throw new TransactionException(new Error(eventTx.rawLog), {
640
+ contextCode: eventTx.code,
641
+ contextModule: eventTx.codespace
642
+ });
643
+ return fetchTx(txHash);
644
+ }
645
+
260
646
  //#endregion
261
647
  //#region src/core/tx/api/TxGrpcApi.ts
262
648
  var TxGrpcApi = class extends BaseGrpcConsumer {
@@ -296,16 +682,24 @@ var TxGrpcApi = class extends BaseGrpcConsumer {
296
682
  });
297
683
  }
298
684
  }
299
- async fetchTxPoll(txHash, timeout = DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS) {
685
+ async fetchTxPoll({ txHash, abortSignal, timeout = DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS, pollingInterval = DEFAULT_TX_POLL_INTERVAL_MS }) {
300
686
  const deadline = Date.now() + timeout;
301
687
  for (let start = Date.now(); start < deadline; start = Date.now()) {
688
+ this.throwIfTxPollingCancelled(abortSignal);
302
689
  try {
303
- const tx = await this.fetchTxDual(txHash, deadline);
690
+ const tx = await this.fetchTxDual({
691
+ txHash,
692
+ deadline,
693
+ abortSignal
694
+ });
695
+ this.throwIfTxPollingCancelled(abortSignal);
304
696
  if (tx) return tx;
305
697
  } catch (e) {
698
+ this.throwIfTxPollingCancelled(abortSignal);
306
699
  if (e instanceof TransactionException) throw e;
307
700
  }
308
- const gap = DEFAULT_TX_POLL_INTERVAL_MS - (Date.now() - start);
701
+ this.throwIfTxPollingCancelled(abortSignal);
702
+ const gap = pollingInterval - (Date.now() - start);
309
703
  if (gap > 0) await sleep(gap);
310
704
  }
311
705
  throw new GrpcUnaryRequestException(/* @__PURE__ */ new Error(`Transaction was not included in a block before timeout of ${timeout}ms`), {
@@ -313,20 +707,57 @@ var TxGrpcApi = class extends BaseGrpcConsumer {
313
707
  contextModule: "fetch-tx-poll"
314
708
  });
315
709
  }
316
- async safeFetchTx(txHash, delay) {
710
+ async waitForTxInclusion({ txHash, timeout = DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS, options }) {
711
+ const txResponse = await (await this.prepareTxInclusionWait({
712
+ txHash,
713
+ timeout,
714
+ options
715
+ })).wait();
716
+ if (!txResponse) throw new GrpcUnaryRequestException(/* @__PURE__ */ new Error(`The transaction with ${txHash} is not found`), {
717
+ context: "TxGrpcApi",
718
+ contextModule: "wait-for-tx-inclusion"
719
+ });
720
+ return txResponse;
721
+ }
722
+ async prepareTxInclusionWait({ txHash, timeout = DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS, options }) {
723
+ return prepareTxInclusionWaiter({
724
+ txHash,
725
+ timeout,
726
+ options,
727
+ fetchTx: (includedTxHash) => this.fetchTx(includedTxHash),
728
+ fetchTxPoll: (args) => this.fetchTxPoll(args),
729
+ createRequestException: (error, contextModule) => new GrpcUnaryRequestException(error, {
730
+ context: "TxGrpcApi",
731
+ contextModule
732
+ })
733
+ });
734
+ }
735
+ async safeFetchTx({ txHash, delay, abortSignal }) {
317
736
  if (delay) await sleep(delay);
737
+ this.throwIfTxPollingCancelled(abortSignal);
318
738
  return this.fetchTx(txHash).catch((e) => {
319
739
  if (e instanceof TransactionException) throw e;
320
740
  return null;
321
741
  });
322
742
  }
323
- fetchTxDual(txHash, deadline) {
743
+ fetchTxDual({ txHash, deadline, abortSignal }) {
324
744
  const STAGGER = 300;
325
745
  const timeout = Math.max(0, Math.min(DEFAULT_TX_POLL_CALL_TIMEOUT_MS, deadline - Date.now()));
326
- const fetches = Promise.all([this.safeFetchTx(txHash), this.safeFetchTx(txHash, STAGGER)]).then(([a, b]) => a !== null && a !== void 0 ? a : b);
746
+ const fetches = Promise.all([this.safeFetchTx({
747
+ txHash,
748
+ abortSignal
749
+ }), this.safeFetchTx({
750
+ txHash,
751
+ delay: STAGGER,
752
+ abortSignal
753
+ })]).then(([a, b]) => a !== null && a !== void 0 ? a : b);
327
754
  fetches.catch(() => {});
328
755
  return Promise.race([fetches, sleep(timeout).then(() => null)]);
329
756
  }
757
+ throwIfTxPollingCancelled(abortSignal) {
758
+ if (!(abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted)) return;
759
+ throw new Error("Transaction inclusion polling was cancelled");
760
+ }
330
761
  async simulate(txRaw) {
331
762
  const txRawClone = CosmosTxV1Beta1TxPb.TxRaw.create({ ...txRaw });
332
763
  const simulateRequest = CosmosTxV1Beta1ServicePb.SimulateRequest.create();
@@ -356,12 +787,19 @@ var TxGrpcApi = class extends BaseGrpcConsumer {
356
787
  }
357
788
  }
358
789
  async broadcast(txRaw, options) {
359
- const mode = (options === null || options === void 0 ? void 0 : options.mode) || CosmosTxV1Beta1ServicePb.BroadcastMode.SYNC;
360
790
  const timeout = (options === null || options === void 0 ? void 0 : options.timeout) || toBigNumber((options === null || options === void 0 ? void 0 : options.txTimeout) || DEFAULT_BLOCK_TIMEOUT_HEIGHT).times(DEFAULT_BLOCK_TIME_IN_SECONDS * 1e3).toNumber();
361
- const broadcastTxRequest = CosmosTxV1Beta1ServicePb.BroadcastTxRequest.create();
362
- broadcastTxRequest.txBytes = CosmosTxV1Beta1TxPb.TxRaw.toBinary(txRaw);
363
- broadcastTxRequest.mode = mode;
791
+ const txHash = TxClient.hash(txRaw);
792
+ let inclusionWaiter;
364
793
  try {
794
+ inclusionWaiter = await this.prepareTxInclusionWait({
795
+ txHash,
796
+ timeout,
797
+ options
798
+ });
799
+ const mode = (options === null || options === void 0 ? void 0 : options.mode) || (inclusionWaiter.inclusionStrategy !== TxInclusionStrategy.Poll ? CosmosTxV1Beta1ServicePb.BroadcastMode.ASYNC : CosmosTxV1Beta1ServicePb.BroadcastMode.SYNC);
800
+ const broadcastTxRequest = CosmosTxV1Beta1ServicePb.BroadcastTxRequest.create();
801
+ broadcastTxRequest.txBytes = CosmosTxV1Beta1TxPb.TxRaw.toBinary(txRaw);
802
+ broadcastTxRequest.mode = mode;
365
803
  const txResponse = (await this.executeGrpcCall(broadcastTxRequest, this.client.broadcastTx.bind(this.client))).txResponse;
366
804
  if (!txResponse) throw new GrpcUnaryRequestException(/* @__PURE__ */ new Error(`The transaction has failed to be broadcasted`), {
367
805
  context: "TxGrpcApi.broadcast",
@@ -372,8 +810,14 @@ var TxGrpcApi = class extends BaseGrpcConsumer {
372
810
  contextModule: txResponse.codespace
373
811
  });
374
812
  if (options === null || options === void 0 ? void 0 : options.onBroadcast) options.onBroadcast(txResponse.txhash);
375
- return await this.fetchTxPoll(txResponse.txhash, timeout);
813
+ const result = await inclusionWaiter.wait(txResponse.txhash);
814
+ if (!result) throw new GrpcUnaryRequestException(/* @__PURE__ */ new Error(`The transaction with ${txResponse.txhash} is not found`), {
815
+ context: "TxGrpcApi.broadcast",
816
+ contextModule: "wait-for-tx-inclusion"
817
+ });
818
+ return result;
376
819
  } catch (e) {
820
+ inclusionWaiter === null || inclusionWaiter === void 0 || inclusionWaiter.close();
377
821
  if (e instanceof TransactionException) throw e;
378
822
  if (e instanceof GrpcUnaryRequestException) throw e;
379
823
  throw new TransactionException(new Error(e));
@@ -460,17 +904,20 @@ var TxRestApi = class {
460
904
  });
461
905
  }
462
906
  }
463
- async fetchTxPoll(txHash, timeout = DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS) {
907
+ async fetchTxPoll({ txHash, timeout = DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS, pollingInterval = DEFAULT_TX_POLL_INTERVAL_MS, abortSignal }) {
464
908
  const deadline = Date.now() + timeout;
465
909
  for (let start = Date.now(); start < deadline; start = Date.now()) {
910
+ this.throwIfTxPollingCancelled(abortSignal);
466
911
  const callTimeout = Math.max(0, Math.min(DEFAULT_TX_POLL_CALL_TIMEOUT_MS, deadline - Date.now()));
467
912
  try {
468
913
  const txResponse = await Promise.race([this.fetchTx(txHash), sleep(callTimeout).then(() => null)]);
469
914
  if (txResponse) return txResponse;
470
915
  } catch (e) {
916
+ this.throwIfTxPollingCancelled(abortSignal);
471
917
  if (e instanceof TransactionException) throw e;
472
918
  }
473
- const remaining = DEFAULT_TX_POLL_INTERVAL_MS - (Date.now() - start);
919
+ this.throwIfTxPollingCancelled(abortSignal);
920
+ const remaining = pollingInterval - (Date.now() - start);
474
921
  if (remaining > 0) await sleep(remaining);
475
922
  }
476
923
  throw new HttpRequestException(/* @__PURE__ */ new Error(`Transaction was not included in a block before timeout of ${timeout}ms`), {
@@ -478,6 +925,35 @@ var TxRestApi = class {
478
925
  contextModule: "TxRestApi.fetch-tx-poll"
479
926
  });
480
927
  }
928
+ throwIfTxPollingCancelled(abortSignal) {
929
+ if (!(abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted)) return;
930
+ throw new Error("Transaction inclusion polling was cancelled");
931
+ }
932
+ async waitForTxInclusion({ txHash, timeout = DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS, options }) {
933
+ const txResponse = await (await this.prepareTxInclusionWait({
934
+ txHash,
935
+ timeout,
936
+ options
937
+ })).wait();
938
+ if (!txResponse) throw new HttpRequestException(/* @__PURE__ */ new Error(`The transaction with ${txHash} is not found`), {
939
+ context: "TxRestApi",
940
+ contextModule: "wait-for-tx-inclusion"
941
+ });
942
+ return txResponse;
943
+ }
944
+ async prepareTxInclusionWait({ txHash, timeout = DEFAULT_TX_BLOCK_INCLUSION_TIMEOUT_IN_MS, options }) {
945
+ return prepareTxInclusionWaiter({
946
+ txHash,
947
+ timeout,
948
+ options,
949
+ fetchTx: (includedTxHash) => this.fetchTx(includedTxHash),
950
+ fetchTxPoll: (args) => this.fetchTxPoll(args),
951
+ createRequestException: (error, contextModule) => new HttpRequestException(error, {
952
+ context: "TxRestApi",
953
+ contextModule
954
+ })
955
+ });
956
+ }
481
957
  async simulate(txRaw) {
482
958
  const txRawClone = CosmosTxV1Beta1TxPb.TxRaw.create({ ...txRaw });
483
959
  if (txRawClone.signatures.length === 0) txRawClone.signatures = [new Uint8Array(0)];
@@ -500,8 +976,15 @@ var TxRestApi = class {
500
976
  }
501
977
  async broadcast(txRaw, options) {
502
978
  const timeout = (options === null || options === void 0 ? void 0 : options.timeout) || toBigNumber((options === null || options === void 0 ? void 0 : options.txTimeout) || DEFAULT_BLOCK_TIMEOUT_HEIGHT).times(DEFAULT_BLOCK_TIME_IN_SECONDS * 1e3).toNumber();
979
+ const txHash = TxClient.hash(txRaw);
980
+ let inclusionWaiter;
503
981
  try {
504
- const { tx_response: txResponse } = await this.broadcastTx(txRaw, BroadcastMode.Sync);
982
+ inclusionWaiter = await this.prepareTxInclusionWait({
983
+ txHash,
984
+ timeout,
985
+ options
986
+ });
987
+ const { tx_response: txResponse } = await this.broadcastTx(txRaw, inclusionWaiter.inclusionStrategy !== TxInclusionStrategy.Poll ? BroadcastMode.Async : BroadcastMode.Sync);
505
988
  if (!txResponse) throw new HttpRequestException(/* @__PURE__ */ new Error("The transaction has failed to be broadcasted"), {
506
989
  context: "TxRestApi.broadcast",
507
990
  contextModule: "broadcast"
@@ -511,8 +994,14 @@ var TxRestApi = class {
511
994
  contextModule: txResponse.codespace
512
995
  });
513
996
  if (options === null || options === void 0 ? void 0 : options.onBroadcast) options.onBroadcast(txResponse.txhash);
514
- return await this.fetchTxPoll(txResponse.txhash, timeout);
997
+ const result = await inclusionWaiter.wait(txResponse.txhash);
998
+ if (!result) throw new HttpRequestException(/* @__PURE__ */ new Error(`The transaction with ${txResponse.txhash} is not found`), {
999
+ context: "TxRestApi.broadcast",
1000
+ contextModule: "wait-for-tx-inclusion"
1001
+ });
1002
+ return result;
515
1003
  } catch (e) {
1004
+ inclusionWaiter === null || inclusionWaiter === void 0 || inclusionWaiter.close();
516
1005
  if (e instanceof HttpRequestException) {
517
1006
  if (e.code !== StatusCodes.OK) throw e;
518
1007
  }
@@ -605,7 +1094,13 @@ var TxRestApi = class {
605
1094
  //#region src/core/tx/api/utils.ts
606
1095
  const waitTxBroadcasted = (txHash, options) => {
607
1096
  const timeout = toBigNumber((options === null || options === void 0 ? void 0 : options.txTimeout) || DEFAULT_BLOCK_TIMEOUT_HEIGHT).times(DEFAULT_BLOCK_TIME_IN_SECONDS * 1e3).toNumber();
608
- return options.endpoints.grpc ? new TxGrpcApi(options.endpoints.grpc).fetchTxPoll(txHash, timeout) : new TxRestApi(options.endpoints.rest).fetchTxPoll(txHash, timeout);
1097
+ return options.endpoints.grpc ? new TxGrpcApi(options.endpoints.grpc).fetchTxPoll({
1098
+ txHash,
1099
+ timeout
1100
+ }) : new TxRestApi(options.endpoints.rest).fetchTxPoll({
1101
+ txHash,
1102
+ timeout
1103
+ });
609
1104
  };
610
1105
 
611
1106
  //#endregion
@@ -636,13 +1131,6 @@ const generateArbitrarySignDoc = (message, signer) => {
636
1131
  };
637
1132
  };
638
1133
 
639
- //#endregion
640
- //#region src/core/tx/types/tx.ts
641
- const TxClientMode = {
642
- gRpc: "grpc",
643
- rest: "rest"
644
- };
645
-
646
1134
  //#endregion
647
1135
  //#region src/core/tx/broadcaster/MsgBroadcasterWithPk.ts
648
1136
  /**
@@ -732,7 +1220,11 @@ var MsgBroadcasterWithPk = class {
732
1220
  chainId: evmChainId,
733
1221
  signature: `0x${uint8ArrayToHex(signature)}`
734
1222
  });
735
- return await new TxGrpcApi(endpoints.grpc).fetchTxPoll(response.txHash);
1223
+ const timeoutInMs = toBigNumber(txTimeout).times(DEFAULT_BLOCK_TIME_IN_SECONDS).times(1e3).toNumber();
1224
+ return await new TxGrpcApi(endpoints.grpc).fetchTxPoll({
1225
+ txHash: response.txHash,
1226
+ timeout: timeoutInMs
1227
+ });
736
1228
  }
737
1229
  /**
738
1230
  * Broadcasting the transaction using the client
@@ -887,4 +1379,4 @@ var MsgBroadcasterWithPk = class {
887
1379
  };
888
1380
 
889
1381
  //#endregion
890
- export { errorToErrorMessage as C, SIGN_EIP712_V2 as S, CosmosTxV1Beta1TxPb as _, TxRestApi as a, SIGN_DIRECT as b, TxGrpcApi as c, createTransactionAndCosmosSignDocForAddressAndMsg as d, createTransactionForAddressAndMsg as f, getTxRawFromTxRawOrDirectSignResponse as g, createTxRawFromSigResponse as h, waitTxBroadcasted as i, createTransaction as l, createTransactionWithSigners as m, TxClientMode as n, BroadcastMode as o, createTransactionFromMsg as p, generateArbitrarySignDoc as r, BroadcastModeKeplr as s, MsgBroadcasterWithPk as t, createTransactionAndCosmosSignDoc as u, TxClient as v, isTxNotFoundError as w, SIGN_EIP712 as x, SIGN_AMINO as y };
1382
+ export { SIGN_DIRECT as C, isTxNotFoundError as D, errorToErrorMessage as E, SIGN_AMINO as S, SIGN_EIP712_V2 as T, createTransactionWithSigners as _, BroadcastMode as a, CosmosTxV1Beta1TxPb as b, normalizeTendermintWebSocketEndpoint as c, TxInclusionStrategy as d, createTransaction as f, createTransactionFromMsg as g, createTransactionForAddressAndMsg as h, TxRestApi as i, subscribeToTendermintTxEvent as l, createTransactionAndCosmosSignDocForAddressAndMsg as m, generateArbitrarySignDoc as n, BroadcastModeKeplr as o, createTransactionAndCosmosSignDoc as p, waitTxBroadcasted as r, TxGrpcApi as s, MsgBroadcasterWithPk as t, TxClientMode as u, createTxRawFromSigResponse as v, SIGN_EIP712 as w, TxClient as x, getTxRawFromTxRawOrDirectSignResponse as y };
@@ -1,6 +1,6 @@
1
1
  import "./tx_pb-DG9OU_HE.js";
2
2
  import "./index-DJtcTm1W.js";
3
- import { $d as cosmosSdkDecToBigNumber, $f as SignTypedDataVersionV4, Ad as hexToBuff, Af as spotPriceFromChainPriceToFixed, Bd as getChecksumAddress, Bf as getErrorMessage, Cd as base64ToUint8Array, Cf as formatPriceToAllowablePrice, Cp as protobufTimestampToUnixSeconds, Dd as fromBase64, Df as isNumber, Ed as concatUint8Arrays, Ef as getTensMultiplier, Fd as uint8ArrayToBase64, Ff as spotQuantityToChainQuantity, Fx as GrpcWebFetchTransport, Gd as getSubaccountId, Gf as isNode, Hd as getEthereumAddress, Hf as hexToNumber, Id as uint8ArrayToHex, If as spotQuantityToChainQuantityToFixed, Jd as getDerivativeMarketDecimals, Jf as objectToJson, Kd as isCw20ContractAddress, Kf as isReactNative, Ld as uint8ArrayToString, Lf as bigIntReplacer, Md as stringToUint8Array, Mf as spotPriceToChainPriceToFixed, Nd as toBase64, Nf as spotQuantityFromChainQuantity, Od as fromUtf8, Of as numberToCosmosSdkDecString, Pd as toUtf8, Pf as spotQuantityFromChainQuantityToFixed, Qd as amountToCosmosSdkDecAmount, Qf as sortObjectByKeysWithReduce, Rd as addHexPrefix, Rf as bigIntToNumber, Sd as DEFAULT_DERIVATION_PATH, Sf as formatPriceToAllowableDecimals, Sp as protobufTimestampToUnixMs, Td as binaryToBase64, Tf as getSignificantDecimalsFromNumber, Ud as getInjectiveAddress, Uf as isBrowser, Vd as getDefaultSubaccountId, Vf as grpcCoinToUiCoin, Wd as getInjectiveAddressFromSubaccountId, Wf as isJsonString, Xd as getSpotMarketDecimals, Xf as safeBigIntStringify, Yd as getDerivativeMarketTensMultiplier, Yf as protoObjectToJson, Zd as getSpotMarketTensMultiplier, Zf as sortObjectByKeys, _d as BECH32_ADDR_CONS_PREFIX, _f as derivativeQuantityToChainQuantityToFixed, _p as getGrpcWebTransport, af as denomAmountToGrpcChainDenomAmount, ap as hashToHex, bd as BECH32_PUBKEY_CONS_PREFIX, bf as formatNumberToAllowableDecimals, bp as makeTimeoutTimestampInNs, cd as recoverTypedSignaturePubKey, cf as derivativeMarginToChainMargin, cp as privateKeyHashToPublicKeyBase64, dd as grpcPagingToPaging, df as derivativePriceFromChainPriceToFixed, dp as publicKeyToAddress, ef as denomAmountFromChainDenomAmount, ep as TypedDataUtilsHashStruct, fd as grpcPagingToPagingV2, ff as derivativePriceToChainPrice, fp as ripemd160, gd as BECH32_ADDR_ACC_PREFIX, gf as derivativeQuantityToChainQuantity, gp as ofacList, hd as paginationUint8ArrayToString, hf as derivativeQuantityFromChainQuantityToFixed, hp as parseCoins, if as denomAmountToChainDenomAmountToFixed, ip as domainHash, jd as hexToUint8Array, jf as spotPriceToChainPrice, kd as hexToBase64, kf as spotPriceFromChainPrice, ld as fetchAllWithPagination, lf as derivativeMarginToChainMarginToFixed, lp as privateKeyToPublicKey, md as paginationRequestFromPagination, mf as derivativeQuantityFromChainQuantity, mp as sha256, nf as denomAmountFromGrpcChainDenomAmount, np as TypedMessageV4, of as derivativeMarginFromChainMargin, op as messageHash, pd as pageRequestToGrpcPageRequestV2, pf as derivativePriceToChainPriceToFixed, pp as sanitizeTypedData, qd as removeHexPrefix, qf as isServerSide, rf as denomAmountToChainDenomAmount, rp as decompressPubKey, sf as derivativeMarginFromChainMarginToFixed, sp as privateKeyHashToPublicKey, tf as denomAmountFromChainDenomAmountToFixed, tp as TypedDataUtilsSanitizeData, ud as grpcPaginationToPagination, uf as derivativePriceFromChainPrice, up as privateKeyToPublicKeyBase64, vd as BECH32_ADDR_VAL_PREFIX, vf as formatAmountToAllowableAmount, vp as getGasPriceBasedOnMessage, wd as base64ToUtf8, wf as getExactDecimalsFromNumber, xd as BECH32_PUBKEY_VAL_PREFIX, xf as formatNumberToAllowableTensMultiplier, xp as protobufTimestampToDate, yd as BECH32_PUBKEY_ACC_PREFIX, yf as formatAmountToAllowableDecimals, yp as makeTimeoutTimestamp, zd as getAddressFromInjectiveAddress, zf as bigIntToString } from "./index-DgmN1YXO.js";
3
+ import { $d as cosmosSdkDecToBigNumber, $f as SignTypedDataVersionV4, Ad as hexToBuff, Af as spotPriceFromChainPriceToFixed, Bd as getChecksumAddress, Bf as getErrorMessage, Cd as base64ToUint8Array, Cf as formatPriceToAllowablePrice, Cp as protobufTimestampToUnixSeconds, Dd as fromBase64, Df as isNumber, Ed as concatUint8Arrays, Ef as getTensMultiplier, Fd as uint8ArrayToBase64, Ff as spotQuantityToChainQuantity, Gd as getSubaccountId, Gf as isNode, Gx as GrpcWebFetchTransport, Hd as getEthereumAddress, Hf as hexToNumber, Id as uint8ArrayToHex, If as spotQuantityToChainQuantityToFixed, Jd as getDerivativeMarketDecimals, Jf as objectToJson, Kd as isCw20ContractAddress, Kf as isReactNative, Ld as uint8ArrayToString, Lf as bigIntReplacer, Md as stringToUint8Array, Mf as spotPriceToChainPriceToFixed, Nd as toBase64, Nf as spotQuantityFromChainQuantity, Od as fromUtf8, Of as numberToCosmosSdkDecString, Pd as toUtf8, Pf as spotQuantityFromChainQuantityToFixed, Qd as amountToCosmosSdkDecAmount, Qf as sortObjectByKeysWithReduce, Rd as addHexPrefix, Rf as bigIntToNumber, Sd as DEFAULT_DERIVATION_PATH, Sf as formatPriceToAllowableDecimals, Sp as protobufTimestampToUnixMs, Td as binaryToBase64, Tf as getSignificantDecimalsFromNumber, Ud as getInjectiveAddress, Uf as isBrowser, Vd as getDefaultSubaccountId, Vf as grpcCoinToUiCoin, Wd as getInjectiveAddressFromSubaccountId, Wf as isJsonString, Xd as getSpotMarketDecimals, Xf as safeBigIntStringify, Yd as getDerivativeMarketTensMultiplier, Yf as protoObjectToJson, Zd as getSpotMarketTensMultiplier, Zf as sortObjectByKeys, _d as BECH32_ADDR_CONS_PREFIX, _f as derivativeQuantityToChainQuantityToFixed, _p as getGrpcWebTransport, af as denomAmountToGrpcChainDenomAmount, ap as hashToHex, bd as BECH32_PUBKEY_CONS_PREFIX, bf as formatNumberToAllowableDecimals, bp as makeTimeoutTimestampInNs, cd as recoverTypedSignaturePubKey, cf as derivativeMarginToChainMargin, cp as privateKeyHashToPublicKeyBase64, dd as grpcPagingToPaging, df as derivativePriceFromChainPriceToFixed, dp as publicKeyToAddress, ef as denomAmountFromChainDenomAmount, ep as TypedDataUtilsHashStruct, fd as grpcPagingToPagingV2, ff as derivativePriceToChainPrice, fp as ripemd160, gd as BECH32_ADDR_ACC_PREFIX, gf as derivativeQuantityToChainQuantity, gp as ofacList, hd as paginationUint8ArrayToString, hf as derivativeQuantityFromChainQuantityToFixed, hp as parseCoins, if as denomAmountToChainDenomAmountToFixed, ip as domainHash, jd as hexToUint8Array, jf as spotPriceToChainPrice, kd as hexToBase64, kf as spotPriceFromChainPrice, ld as fetchAllWithPagination, lf as derivativeMarginToChainMarginToFixed, lp as privateKeyToPublicKey, md as paginationRequestFromPagination, mf as derivativeQuantityFromChainQuantity, mp as sha256, nf as denomAmountFromGrpcChainDenomAmount, np as TypedMessageV4, of as derivativeMarginFromChainMargin, op as messageHash, pd as pageRequestToGrpcPageRequestV2, pf as derivativePriceToChainPriceToFixed, pp as sanitizeTypedData, qd as removeHexPrefix, qf as isServerSide, rf as denomAmountToChainDenomAmount, rp as decompressPubKey, sf as derivativeMarginFromChainMarginToFixed, sp as privateKeyHashToPublicKey, tf as denomAmountFromChainDenomAmountToFixed, tp as TypedDataUtilsSanitizeData, ud as grpcPaginationToPagination, uf as derivativePriceFromChainPrice, up as privateKeyToPublicKeyBase64, vd as BECH32_ADDR_VAL_PREFIX, vf as formatAmountToAllowableAmount, vp as getGasPriceBasedOnMessage, wd as base64ToUtf8, wf as getExactDecimalsFromNumber, xd as BECH32_PUBKEY_VAL_PREFIX, xf as formatNumberToAllowableTensMultiplier, xp as protobufTimestampToDate, yd as BECH32_PUBKEY_ACC_PREFIX, yf as formatAmountToAllowableDecimals, yp as makeTimeoutTimestamp, zd as getAddressFromInjectiveAddress, zf as bigIntToString } from "./index-DXDWfiZz.js";
4
4
  import "./BaseGrpcConsumer-BptQBj1l.js";
5
5
  import "./index-BSAdUyzU.js";
6
6
  import "./index-sT17wTBx.js";