@pushchain/core 5.1.5-alpha.0 → 5.1.5-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushchain/core",
3
- "version": "5.1.5-alpha.0",
3
+ "version": "5.1.5-alpha.1",
4
4
  "homepage": "https://push.org",
5
5
  "keywords": [
6
6
  "pushchain",
@@ -28,6 +28,8 @@ const uea_manager_1 = require("./uea-manager");
28
28
  const gas_calculator_1 = require("./gas-calculator");
29
29
  const route_handlers_1 = require("./route-handlers");
30
30
  const build_payload_1 = require("../svm-idl/build-payload");
31
+ const progress_hook_types_1 = require("../../progress-hook/progress-hook.types");
32
+ const progress_hook_1 = tslib_1.__importDefault(require("../../progress-hook/progress-hook"));
31
33
  // ============================================================================
32
34
  // prepareTransaction
33
35
  // ============================================================================
@@ -775,8 +777,8 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks) {
775
777
  hops: hopInfos,
776
778
  hopCount: hops.length,
777
779
  waitForAll: (opts) => tslib_1.__awaiter(this, void 0, void 0, function* () {
778
- var _a;
779
- const { pollingIntervalMs = 10000, timeout = 300000, progressHook: cascadeProgressHook, } = opts || {};
780
+ var _a, _b;
781
+ const { pollingIntervalMs = 10000, timeout = 300000, progressHook: cascadeProgressHook, eventHook, } = opts || {};
780
782
  const startTime = Date.now();
781
783
  try {
782
784
  // 1. Wait for initial Push Chain tx confirmation
@@ -841,12 +843,14 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks) {
841
843
  status: 'timeout',
842
844
  elapsed: Date.now() - startTime,
843
845
  });
846
+ eventHook === null || eventHook === void 0 ? void 0 : eventHook(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_04](Date.now() - startTime));
844
847
  return {
845
848
  success: false,
846
849
  hops: hopInfos,
847
850
  failedAt: hop.hopIndex,
848
851
  };
849
852
  }
853
+ eventHook === null || eventHook === void 0 ? void 0 : eventHook(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_08_01](hop.executionChain));
850
854
  cascadeProgressHook === null || cascadeProgressHook === void 0 ? void 0 : cascadeProgressHook({
851
855
  hopIndex: hop.hopIndex,
852
856
  route: hop.route,
@@ -854,6 +858,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks) {
854
858
  status: 'polling',
855
859
  elapsed: Date.now() - startTime,
856
860
  });
861
+ let lastEmittedStatus;
857
862
  try {
858
863
  const outboundDetails = yield callbacks.waitForOutboundTxFn(response.hash, {
859
864
  initialWaitMs: Math.min(60000, remainingTimeout),
@@ -867,11 +872,17 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks) {
867
872
  status: event.status,
868
873
  elapsed: Date.now() - startTime,
869
874
  });
875
+ if (event.status === 'polling' &&
876
+ lastEmittedStatus !== 'polling') {
877
+ lastEmittedStatus = 'polling';
878
+ eventHook === null || eventHook === void 0 ? void 0 : eventHook(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_08_02](event.elapsed));
879
+ }
870
880
  },
871
881
  });
872
882
  hop.status = 'confirmed';
873
883
  hop.txHash = outboundDetails.externalTxHash;
874
884
  hop.outboundDetails = outboundDetails;
885
+ eventHook === null || eventHook === void 0 ? void 0 : eventHook(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_03](outboundDetails));
875
886
  cascadeProgressHook === null || cascadeProgressHook === void 0 ? void 0 : cascadeProgressHook({
876
887
  hopIndex: hop.hopIndex,
877
888
  route: hop.route,
@@ -882,6 +893,11 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks) {
882
893
  });
883
894
  }
884
895
  catch (err) {
896
+ const errMsg = err instanceof Error ? err.message : String(err);
897
+ const isTimeout = errMsg.startsWith('Timeout waiting for outbound transaction');
898
+ eventHook === null || eventHook === void 0 ? void 0 : eventHook(isTimeout
899
+ ? progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_04](remainingTimeout)
900
+ : progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_05](errMsg));
885
901
  hop.status = 'failed';
886
902
  cascadeProgressHook === null || cascadeProgressHook === void 0 ? void 0 : cascadeProgressHook({
887
903
  hopIndex: hop.hopIndex,
@@ -899,6 +915,13 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks) {
899
915
  }
900
916
  else {
901
917
  // Multiple outbound hops: use V2 API which returns outboundTx[]
918
+ // Emit "Awaiting External Chain" once per outbound hop before
919
+ // polling begins.
920
+ for (const outHop of outboundHops) {
921
+ eventHook === null || eventHook === void 0 ? void 0 : eventHook(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_08_01](outHop.executionChain));
922
+ }
923
+ const perHopLastStatus = new Map();
924
+ const confirmedHops = new Set();
902
925
  const allOutboundDetails = yield callbacks.waitForAllOutboundTxsFn(response.hash, outboundHops, {
903
926
  initialWaitMs: Math.min(60000, timeout - (Date.now() - startTime)),
904
927
  pollingIntervalMs,
@@ -912,13 +935,39 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks) {
912
935
  txHash: event.txHash,
913
936
  elapsed: Date.now() - startTime,
914
937
  });
938
+ const prev = perHopLastStatus.get(event.hopIndex);
939
+ if (event.status === 'polling' &&
940
+ prev !== 'polling') {
941
+ perHopLastStatus.set(event.hopIndex, 'polling');
942
+ eventHook === null || eventHook === void 0 ? void 0 : eventHook(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_08_02](Date.now() - startTime));
943
+ }
944
+ if (event.status === 'confirmed' &&
945
+ event.txHash &&
946
+ !confirmedHops.has(event.hopIndex)) {
947
+ // waitForAllOutboundTxsV2 populates hop.outboundDetails
948
+ // on the matched hop before emitting 'confirmed' (see
949
+ // outbound-sync.ts:348-355). Auto-promotion paths
950
+ // without a txHash are skipped by the `event.txHash`
951
+ // guard above, so we only reach here with full details.
952
+ const matchedHop = outboundHops.find((h) => h.hopIndex === event.hopIndex);
953
+ if (matchedHop === null || matchedHop === void 0 ? void 0 : matchedHop.outboundDetails) {
954
+ confirmedHops.add(event.hopIndex);
955
+ eventHook === null || eventHook === void 0 ? void 0 : eventHook(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_03](matchedHop.outboundDetails));
956
+ }
957
+ }
915
958
  },
916
959
  });
917
960
  if (!allOutboundDetails.success) {
961
+ const failedIdx = (_b = allOutboundDetails.failedAt) !== null && _b !== void 0 ? _b : 0;
962
+ const failedHop = outboundHops.find((h) => h.hopIndex === failedIdx);
963
+ const failMsg = failedHop
964
+ ? `Outbound failed for hop ${failedIdx} on ${failedHop.executionChain}`
965
+ : `Outbound cascade failed at hop ${failedIdx}`;
966
+ eventHook === null || eventHook === void 0 ? void 0 : eventHook(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_05](failMsg));
918
967
  return {
919
968
  success: false,
920
969
  hops: hopInfos,
921
- failedAt: allOutboundDetails.failedAt,
970
+ failedAt: failedIdx,
922
971
  };
923
972
  }
924
973
  }
@@ -16,6 +16,8 @@ const viem_1 = require("viem");
16
16
  const uea_evm_1 = require("../../constants/abi/uea.evm");
17
17
  const chain_1 = require("../../constants/chain");
18
18
  const enums_1 = require("../../constants/enums");
19
+ const progress_hook_types_1 = require("../../progress-hook/progress-hook.types");
20
+ const progress_hook_1 = tslib_1.__importDefault(require("../../progress-hook/progress-hook"));
19
21
  const account_1 = require("../../universal/account/account");
20
22
  const push_client_1 = require("../../push-client/push-client");
21
23
  const route_detector_1 = require("../route-detector");
@@ -472,19 +474,40 @@ function transformToUniversalTxResponse(ctx_1, tx_1) {
472
474
  ? (0, route_detector_1.getRouteInfo)(universalTxResponse.route)
473
475
  : undefined;
474
476
  if (routeInfo === null || routeInfo === void 0 ? void 0 : routeInfo.isOutbound) {
477
+ // Response-level only — NOT routed through ctx.progressHook because
478
+ // the default ui-kit toast lacks icon/hide-timer handling for these
479
+ // events. A follow-up ui-kit PR will add handling and can route
480
+ // through both hooks.
481
+ registeredProgressHook === null || registeredProgressHook === void 0 ? void 0 : registeredProgressHook(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_08_01]());
482
+ let lastEmittedStatus;
483
+ const outboundTranslator = (event) => {
484
+ if (!registeredProgressHook)
485
+ return;
486
+ if (event.status === 'polling' && lastEmittedStatus !== 'polling') {
487
+ lastEmittedStatus = 'polling';
488
+ registeredProgressHook(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_08_02](event.elapsed));
489
+ }
490
+ };
475
491
  try {
476
492
  const outboundDetails = yield callbacks.waitForOutboundTx(tx.hash, {
477
493
  initialWaitMs: callbacks.outboundConstants.initialWaitMs,
478
494
  pollingIntervalMs: callbacks.outboundConstants.pollingIntervalMs,
479
495
  timeout: callbacks.outboundConstants.maxTimeoutMs,
496
+ progressHook: outboundTranslator,
480
497
  });
498
+ registeredProgressHook === null || registeredProgressHook === void 0 ? void 0 : registeredProgressHook(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_03](outboundDetails));
481
499
  // Merge external chain details into receipt
482
500
  baseReceipt = Object.assign(Object.assign({}, baseReceipt), { externalTxHash: outboundDetails.externalTxHash, externalChain: outboundDetails.destinationChain, externalExplorerUrl: outboundDetails.explorerUrl, externalRecipient: outboundDetails.recipient, externalAmount: outboundDetails.amount, externalAssetAddr: outboundDetails.assetAddr });
483
501
  }
484
502
  catch (error) {
503
+ const errMsg = error instanceof Error ? error.message : String(error);
504
+ const isTimeout = errMsg.startsWith('Timeout waiting for outbound transaction');
505
+ registeredProgressHook === null || registeredProgressHook === void 0 ? void 0 : registeredProgressHook(isTimeout
506
+ ? progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_04](callbacks.outboundConstants.maxTimeoutMs)
507
+ : progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_05](errMsg));
485
508
  // Outbound polling timed out - return partial receipt (don't throw)
486
509
  // Push Chain tx succeeded, external tracking can be retried later
487
- callbacks.printLog(`[wait] External chain tracking failed: ${error instanceof Error ? error.message : String(error)}`);
510
+ callbacks.printLog(`[wait] External chain tracking failed: ${errMsg}`);
488
511
  }
489
512
  }
490
513
  return baseReceipt;
@@ -138,7 +138,10 @@ export interface UniversalTxResponse {
138
138
  wait: () => Promise<UniversalTxReceipt>;
139
139
  /**
140
140
  * Register a progress callback for events during wait().
141
- * Call this BEFORE calling wait() to receive tracking events.
141
+ * Call this BEFORE calling wait() to receive tracking events, including
142
+ * the SEND-TX-08-xx / SEND-TX-99-03/04/05 external chain polling events
143
+ * emitted on outbound routes. Registering after wait() resolves will
144
+ * replay the pre-execution event buffer but miss outbound polling events.
142
145
  * @param callback - Function called with each progress event
143
146
  */
144
147
  progressHook: (callback: (event: import('../progress-hook/progress-hook.types').ProgressEvent) => void) => void;
@@ -515,8 +518,14 @@ export interface CascadeTrackOptions {
515
518
  pollingIntervalMs?: number;
516
519
  /** Total timeout (default: 600000ms = 10 min) */
517
520
  timeout?: number;
518
- /** Progress callback */
521
+ /** Per-hop progress callback */
519
522
  progressHook?: (event: CascadeProgressEvent) => void;
523
+ /**
524
+ * Unified ProgressEvent stream for SEND-TX-08/99_03-05 telemetry.
525
+ * Fires per outbound hop during external chain polling. Use alongside
526
+ * `progressHook` — they emit complementary views of the same events.
527
+ */
528
+ eventHook?: (event: import('../progress-hook/progress-hook.types').ProgressEvent) => void;
520
529
  }
521
530
  /**
522
531
  * Progress event emitted during cascade tracking
@@ -158,6 +158,25 @@ const RAW_HOOKS = {
158
158
  response: null,
159
159
  level: 'INFO',
160
160
  }),
161
+ // External chain polling (08-x) — emitted from .wait() / cascade.waitForAll()
162
+ // after Push Chain tx success, while the SDK polls the relay for the
163
+ // external chain tx hash on outbound routes.
164
+ [progress_hook_types_1.PROGRESS_HOOK.SEND_TX_08_01]: (destinationChain) => ({
165
+ id: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_08_01,
166
+ title: 'Awaiting External Chain',
167
+ message: destinationChain
168
+ ? `Waiting for relay to dispatch to ${destinationChain}...`
169
+ : 'Waiting for relay to dispatch to external chain...',
170
+ response: null,
171
+ level: 'INFO',
172
+ }),
173
+ [progress_hook_types_1.PROGRESS_HOOK.SEND_TX_08_02]: (elapsedMs) => ({
174
+ id: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_08_02,
175
+ title: 'Polling External Chain',
176
+ message: `Polling relay for external transaction hash (elapsed: ${Math.round(elapsedMs / 1000)}s)`,
177
+ response: null,
178
+ level: 'INFO',
179
+ }),
161
180
  [progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_01]: (txResponse) => ({
162
181
  id: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_01,
163
182
  title: 'Push Chain Tx Success',
@@ -172,6 +191,27 @@ const RAW_HOOKS = {
172
191
  response: null,
173
192
  level: 'ERROR',
174
193
  }),
194
+ [progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_03]: (details) => ({
195
+ id: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_03,
196
+ title: 'External Chain Tx Confirmed',
197
+ message: `External tx confirmed on ${details.destinationChain}: ${details.externalTxHash}`,
198
+ response: details,
199
+ level: 'SUCCESS',
200
+ }),
201
+ [progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_04]: (elapsedMs) => ({
202
+ id: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_04,
203
+ title: 'External Chain Tx Timeout',
204
+ message: `Timed out waiting for external chain tx after ${Math.round(elapsedMs / 1000)}s. Push Chain tx succeeded; the relay may still be processing.`,
205
+ response: null,
206
+ level: 'WARNING',
207
+ }),
208
+ [progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_05]: (errorMessage) => ({
209
+ id: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_99_05,
210
+ title: 'External Chain Tx Failed',
211
+ message: errorMessage,
212
+ response: null,
213
+ level: 'ERROR',
214
+ }),
175
215
  // UEA Migration hooks
176
216
  [progress_hook_types_1.PROGRESS_HOOK.UEA_MIG_01]: () => ({
177
217
  id: progress_hook_types_1.PROGRESS_HOOK.UEA_MIG_01,
@@ -34,8 +34,13 @@ export declare enum PROGRESS_HOOK {
34
34
  SEND_TX_06_05 = "SEND-TX-06-05",// Syncing with Push Chain
35
35
  SEND_TX_06_06 = "SEND-TX-06-06",// Funds Credited on Push Chain (was 06_05)
36
36
  SEND_TX_07 = "SEND-TX-07",// Broadcasting to Push Chain
37
+ SEND_TX_08_01 = "SEND-TX-08-01",// Awaiting External Chain
38
+ SEND_TX_08_02 = "SEND-TX-08-02",// Polling External Chain
37
39
  SEND_TX_99_01 = "SEND-TX-99-01",
38
40
  SEND_TX_99_02 = "SEND-TX-99-02",
41
+ SEND_TX_99_03 = "SEND-TX-99-03",// External Chain Tx Confirmed (SUCCESS)
42
+ SEND_TX_99_04 = "SEND-TX-99-04",// External Chain Tx Timeout (WARNING)
43
+ SEND_TX_99_05 = "SEND-TX-99-05",// External Chain Tx Failed (ERROR)
39
44
  UEA_MIG_01 = "UEA-MIG-01",
40
45
  UEA_MIG_02 = "UEA-MIG-02",
41
46
  UEA_MIG_03 = "UEA-MIG-03",
@@ -28,9 +28,15 @@ var PROGRESS_HOOK;
28
28
  PROGRESS_HOOK["SEND_TX_06_06"] = "SEND-TX-06-06";
29
29
  // 07-x: Execution / broadcasting flow
30
30
  PROGRESS_HOOK["SEND_TX_07"] = "SEND-TX-07";
31
+ // 08-x: External chain polling (after Push Chain tx success, outbound routes)
32
+ PROGRESS_HOOK["SEND_TX_08_01"] = "SEND-TX-08-01";
33
+ PROGRESS_HOOK["SEND_TX_08_02"] = "SEND-TX-08-02";
31
34
  // 99-x: Final outcome
32
35
  PROGRESS_HOOK["SEND_TX_99_01"] = "SEND-TX-99-01";
33
36
  PROGRESS_HOOK["SEND_TX_99_02"] = "SEND-TX-99-02";
37
+ PROGRESS_HOOK["SEND_TX_99_03"] = "SEND-TX-99-03";
38
+ PROGRESS_HOOK["SEND_TX_99_04"] = "SEND-TX-99-04";
39
+ PROGRESS_HOOK["SEND_TX_99_05"] = "SEND-TX-99-05";
34
40
  // UEA Migration hooks
35
41
  PROGRESS_HOOK["UEA_MIG_01"] = "UEA-MIG-01";
36
42
  PROGRESS_HOOK["UEA_MIG_02"] = "UEA-MIG-02";