@pushchain/core 6.0.3 → 6.0.5

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": "6.0.3",
3
+ "version": "6.0.5",
4
4
  "homepage": "https://push.org",
5
5
  "keywords": [
6
6
  "pushchain",
@@ -0,0 +1,5 @@
1
+ import type { ExecuteParams } from './orchestrator.types';
2
+ type PayloadData = ExecuteParams['data'];
3
+ export declare function hasExecutablePayloadData(data: PayloadData): boolean;
4
+ export declare function isEmptyPayloadData(data: PayloadData): boolean;
5
+ export {};
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hasExecutablePayloadData = hasExecutablePayloadData;
4
+ exports.isEmptyPayloadData = isEmptyPayloadData;
5
+ function hasExecutablePayloadData(data) {
6
+ return !(data === undefined ||
7
+ data === '0x' ||
8
+ (Array.isArray(data) && data.length === 0));
9
+ }
10
+ function isEmptyPayloadData(data) {
11
+ return !hasExecutablePayloadData(data);
12
+ }
13
+ //# sourceMappingURL=data-utils.js.map
@@ -23,6 +23,7 @@ const selectors_1 = require("../../constants/selectors");
23
23
  const route_detector_1 = require("../route-detector");
24
24
  const cea_utils_1 = require("../cea-utils");
25
25
  const payload_builders_1 = require("../payload-builders");
26
+ const data_utils_1 = require("../data-utils");
26
27
  const push_chain_1 = require("../../push-chain/push-chain");
27
28
  const context_1 = require("./context");
28
29
  const helpers_1 = require("./helpers");
@@ -122,7 +123,7 @@ function prepareTransaction(ctx, params, callbacks) {
122
123
  // ============================================================================
123
124
  function buildHopDescriptor(ctx, params, route, ueaAddress) {
124
125
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
125
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
126
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
126
127
  // Pass 0 when user omits gasLimit so the contract uses the per-chain base,
127
128
  // except EVM Route 3 where a CEA deploy + sendUniversalTxToUEA needs more
128
129
  // than the generic 500k source-chain base.
@@ -258,7 +259,8 @@ function buildHopDescriptor(ctx, params, route, ueaAddress) {
258
259
  }
259
260
  // Build CEA multicalls
260
261
  const ceaMulticalls = [];
261
- if (params.data) {
262
+ const hasData = (0, data_utils_1.hasExecutablePayloadData)(params.data);
263
+ if (hasData) {
262
264
  if (Array.isArray(params.data)) {
263
265
  ceaMulticalls.push(...params.data);
264
266
  }
@@ -291,42 +293,39 @@ function buildHopDescriptor(ctx, params, route, ueaAddress) {
291
293
  });
292
294
  }
293
295
  }
294
- else if (params.value) {
295
- // Skip multicall when sending native value to own CEA — gateway deposits directly.
296
- // Self-call with value would revert (CEA._handleMulticall rejects it).
297
- if (target.address.toLowerCase() !== ceaAddress.toLowerCase()) {
296
+ else {
297
+ const token = ((_k = params.funds) === null || _k === void 0 ? void 0 : _k.amount)
298
+ ? params.funds.token
299
+ : undefined;
300
+ if (((_l = params.funds) === null || _l === void 0 ? void 0 : _l.amount) && token && token.mechanism !== 'native') {
301
+ const erc20Transfer = (0, viem_1.encodeFunctionData)({
302
+ abi: erc20_evm_1.ERC20_EVM,
303
+ functionName: 'transfer',
304
+ args: [target.address, params.funds.amount],
305
+ });
298
306
  ceaMulticalls.push({
299
- to: target.address,
300
- value: params.value,
301
- data: '0x',
307
+ to: token.address,
308
+ value: BigInt(0),
309
+ data: erc20Transfer,
302
310
  });
303
311
  }
304
- }
305
- else if ((_k = params.funds) === null || _k === void 0 ? void 0 : _k.amount) {
306
- // Funds-only transfer (no data, no value). Without this branch the
307
- // CEA multicall is empty and relayed funds stay in the CEA instead
308
- // of reaching the caller's recipient.
309
- const token = params.funds.token;
310
- if (token) {
311
- if (token.mechanism === 'native') {
312
- if (target.address.toLowerCase() !== ceaAddress.toLowerCase()) {
313
- ceaMulticalls.push({
314
- to: target.address,
315
- value: params.funds.amount,
316
- data: '0x',
317
- });
318
- }
319
- }
320
- else {
321
- const erc20Transfer = (0, viem_1.encodeFunctionData)({
322
- abi: erc20_evm_1.ERC20_EVM,
323
- functionName: 'transfer',
324
- args: [target.address, params.funds.amount],
312
+ if (params.value) {
313
+ // Skip multicall when sending native value to own CEA — gateway deposits directly.
314
+ // Self-call with value would revert (CEA._handleMulticall rejects it).
315
+ if (target.address.toLowerCase() !== ceaAddress.toLowerCase()) {
316
+ ceaMulticalls.push({
317
+ to: target.address,
318
+ value: params.value,
319
+ data: '0x',
325
320
  });
321
+ }
322
+ }
323
+ else if (((_m = params.funds) === null || _m === void 0 ? void 0 : _m.amount) && (token === null || token === void 0 ? void 0 : token.mechanism) === 'native') {
324
+ if (target.address.toLowerCase() !== ceaAddress.toLowerCase()) {
326
325
  ceaMulticalls.push({
327
- to: token.address,
328
- value: BigInt(0),
329
- data: erc20Transfer,
326
+ to: target.address,
327
+ value: params.funds.amount,
328
+ data: '0x',
330
329
  });
331
330
  }
332
331
  }
@@ -334,7 +333,7 @@ function buildHopDescriptor(ctx, params, route, ueaAddress) {
334
333
  // Determine PRC-20 token and burn amount
335
334
  let prc20Token = selectors_1.ZERO_ADDRESS;
336
335
  let burnAmount = BigInt(0);
337
- if ((_l = params.funds) === null || _l === void 0 ? void 0 : _l.amount) {
336
+ if ((_o = params.funds) === null || _o === void 0 ? void 0 : _o.amount) {
338
337
  const token = params.funds.token;
339
338
  if (token) {
340
339
  prc20Token = push_chain_1.PushChain.utils.tokens.getPRC20Address(token).address;
@@ -345,7 +344,7 @@ function buildHopDescriptor(ctx, params, route, ueaAddress) {
345
344
  prc20Token = (0, helpers_1.getNativePRC20ForChain)(targetChain, ctx.pushNetwork);
346
345
  burnAmount = params.value;
347
346
  }
348
- else if (params.data) {
347
+ else if ((0, data_utils_1.hasExecutablePayloadData)(params.data)) {
349
348
  // PAYLOAD-only (no value transfer): still need native PRC-20 token for
350
349
  // chain namespace lookup + gas fees, but burn amount must be zero.
351
350
  // Matches the direct executeUoaToCea path (route-handlers.ts).
@@ -379,7 +378,7 @@ function buildHopDescriptor(ctx, params, route, ueaAddress) {
379
378
  case route_detector_1.TransactionRoute.CEA_TO_PUSH: {
380
379
  // Route 3: Build CEA multicalls for sendUniversalTxFromCEA
381
380
  const sourceChain = params.from.chain;
382
- const seedAmount = (_m = params.value) !== null && _m !== void 0 ? _m : BigInt(0);
381
+ const seedAmount = (_p = params.value) !== null && _p !== void 0 ? _p : BigInt(0);
383
382
  if (isValueOnlyNativeSeedToOwnUea(params, ueaAddress)) {
384
383
  return Object.assign(Object.assign({}, baseDescriptor), { sourceChain, burnAmount: BigInt(0), gasToken: selectors_1.ZERO_ADDRESS, gasFee: BigInt(0), nativeSeedOnly: true, nativeSeedAmount: seedAmount });
385
384
  }
@@ -399,7 +398,7 @@ function buildHopDescriptor(ctx, params, route, ueaAddress) {
399
398
  Buffer.from(ceaPda.toBytes()).toString('hex'));
400
399
  let amount = BigInt(0);
401
400
  let prc20Token;
402
- if (((_o = params.funds) === null || _o === void 0 ? void 0 : _o.amount) && params.funds.amount > BigInt(0)) {
401
+ if (((_q = params.funds) === null || _q === void 0 ? void 0 : _q.amount) && params.funds.amount > BigInt(0)) {
403
402
  amount = params.funds.amount;
404
403
  const token = params.funds.token;
405
404
  if (token && token.address) {
@@ -447,14 +446,14 @@ function buildHopDescriptor(ctx, params, route, ueaAddress) {
447
446
  gasFee,
448
447
  gasPrice, gasLimit: effectiveGasLimit, sizing });
449
448
  }
450
- const { cea: ceaAddress } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, sourceChain, (_p = ctx.rpcUrls[sourceChain]) === null || _p === void 0 ? void 0 : _p[0]);
449
+ const { cea: ceaAddress } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, sourceChain, (_r = ctx.rpcUrls[sourceChain]) === null || _r === void 0 ? void 0 : _r[0]);
451
450
  // CEA auto-deploys on-chain: Vault.finalizeUniversalTx calls CEAFactory.deployCEA()
452
451
  // if CEA doesn't exist yet. No SDK-side blocking needed.
453
452
  // Determine token/amount for the inbound
454
453
  let tokenAddress = selectors_1.ZERO_ADDRESS;
455
454
  let amount = BigInt(0);
456
455
  let nativeValue = BigInt(0);
457
- if ((_q = params.funds) === null || _q === void 0 ? void 0 : _q.amount) {
456
+ if ((_s = params.funds) === null || _s === void 0 ? void 0 : _s.amount) {
458
457
  const token = params.funds.token;
459
458
  if (token) {
460
459
  if (token.mechanism === 'native') {
@@ -644,16 +643,11 @@ function getSegmentType(route) {
644
643
  function sumMulticallNativeValue(multicalls) {
645
644
  return (multicalls !== null && multicalls !== void 0 ? multicalls : []).reduce((sum, mc) => { var _a; return sum + ((_a = mc.value) !== null && _a !== void 0 ? _a : BigInt(0)); }, BigInt(0));
646
645
  }
647
- function isEmptyPayloadData(data) {
648
- return (data === undefined ||
649
- data === '0x' ||
650
- (Array.isArray(data) && data.length === 0));
651
- }
652
646
  function isValueOnlyNativeSeedToOwnUea(params, ueaAddress) {
653
647
  var _a, _b;
654
648
  return (((_a = params.value) !== null && _a !== void 0 ? _a : BigInt(0)) > BigInt(0) &&
655
649
  !((_b = params.funds) === null || _b === void 0 ? void 0 : _b.amount) &&
656
- isEmptyPayloadData(params.data) &&
650
+ (0, data_utils_1.isEmptyPayloadData)(params.data) &&
657
651
  typeof params.to === 'string' &&
658
652
  params.to.toLowerCase() === ueaAddress.toLowerCase());
659
653
  }
@@ -1058,7 +1052,7 @@ function composeCascadeDetailed(ctx, segments, ueaAddress, ueaBalance, ueaNonce,
1058
1052
  // UEA multicall so no nested outbound is needed.
1059
1053
  const mergedHopMulticalls = [];
1060
1054
  for (const h of segment.hops) {
1061
- if (((_j = h === null || h === void 0 ? void 0 : h.params) === null || _j === void 0 ? void 0 : _j.data) || ((_k = h === null || h === void 0 ? void 0 : h.params) === null || _k === void 0 ? void 0 : _k.value)) {
1055
+ if ((0, data_utils_1.hasExecutablePayloadData)((_j = h === null || h === void 0 ? void 0 : h.params) === null || _j === void 0 ? void 0 : _j.data) || ((_k = h === null || h === void 0 ? void 0 : h.params) === null || _k === void 0 ? void 0 : _k.value)) {
1062
1056
  const hopCalls = (0, payload_builders_1.buildExecuteMulticall)({
1063
1057
  execute: {
1064
1058
  to: h.params.to,
@@ -1066,6 +1060,7 @@ function composeCascadeDetailed(ctx, segments, ueaAddress, ueaBalance, ueaNonce,
1066
1060
  data: h.params.data,
1067
1061
  },
1068
1062
  ueaAddress,
1063
+ allowSelfValueCall: true,
1069
1064
  });
1070
1065
  mergedHopMulticalls.push(...hopCalls);
1071
1066
  }
@@ -1270,6 +1265,31 @@ function composeCascade(ctx, segments, ueaAddress, ueaBalance, ueaNonce) {
1270
1265
  // ============================================================================
1271
1266
  // createCascadedBuilder
1272
1267
  // ============================================================================
1268
+ function txHashFromProgressEvent(event) {
1269
+ var _a, _b, _c, _d;
1270
+ const response = event.response;
1271
+ return (_d = (_a = response === null || response === void 0 ? void 0 : response.txHash) !== null && _a !== void 0 ? _a : (_c = (_b = response === null || response === void 0 ? void 0 : response.response) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.hash) !== null && _d !== void 0 ? _d : '';
1272
+ }
1273
+ function withMultihopRootProgressMapping(ctx, run) {
1274
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
1275
+ const originalHook = ctx.progressHook;
1276
+ if (!originalHook)
1277
+ return run();
1278
+ ctx.progressHook = (event) => {
1279
+ if (event.id === progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_01) {
1280
+ originalHook(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_99](txHashFromProgressEvent(event)));
1281
+ return;
1282
+ }
1283
+ originalHook(event);
1284
+ };
1285
+ try {
1286
+ return yield run();
1287
+ }
1288
+ finally {
1289
+ ctx.progressHook = originalHook;
1290
+ }
1291
+ });
1292
+ }
1273
1293
  function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1274
1294
  return {
1275
1295
  send: () => tslib_1.__awaiter(this, void 0, void 0, function* () {
@@ -1298,6 +1318,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1298
1318
  },
1299
1319
  ],
1300
1320
  hopCount: 1,
1321
+ finalTxHash: response.hash,
1301
1322
  waitForAll: () => tslib_1.__awaiter(this, void 0, void 0, function* () {
1302
1323
  return ({
1303
1324
  success: true,
@@ -1310,6 +1331,8 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1310
1331
  txHash: response.hash,
1311
1332
  },
1312
1333
  ],
1334
+ finalTxHash: response.hash,
1335
+ finalTxResponse: singleRoute1Result,
1313
1336
  });
1314
1337
  }),
1315
1338
  wait: (opts) => tslib_1.__awaiter(this, void 0, void 0, function* () { return singleRoute1Result.waitForAll(opts); }),
@@ -1333,6 +1356,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1333
1356
  },
1334
1357
  ],
1335
1358
  hopCount: 1,
1359
+ finalTxHash: response.hash,
1336
1360
  waitForAll: () => tslib_1.__awaiter(this, void 0, void 0, function* () {
1337
1361
  return ({
1338
1362
  success: true,
@@ -1345,6 +1369,8 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1345
1369
  txHash: response.hash,
1346
1370
  },
1347
1371
  ],
1372
+ finalTxHash: response.hash,
1373
+ finalTxResponse: singleRoute2Result,
1348
1374
  });
1349
1375
  }),
1350
1376
  wait: (opts) => tslib_1.__awaiter(this, void 0, void 0, function* () { return singleRoute2Result.waitForAll(opts); }),
@@ -1385,7 +1411,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1385
1411
  value: cascadeRequiredNativeValue,
1386
1412
  data: composedMulticalls,
1387
1413
  };
1388
- const response = yield callbacks.executeFn(executeParams);
1414
+ const response = yield withMultihopRootProgressMapping(ctx, () => callbacks.executeFn(executeParams));
1389
1415
  // Build hop info for tracking
1390
1416
  const hopInfos = hops.map((hop, index) => ({
1391
1417
  hopIndex: index,
@@ -1463,6 +1489,34 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1463
1489
  return;
1464
1490
  emitHopEvent(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_999_03](failedIdx0 + 1, totalHops));
1465
1491
  };
1492
+ const emitRouteIntermediateComplete = (hop, txHash) => {
1493
+ var _a;
1494
+ if (!isMulti)
1495
+ return;
1496
+ const n = hop.hopIndex + 1;
1497
+ if (n >= totalHops)
1498
+ return; // final terminal is 999-01
1499
+ const resolvedTxHash = (_a = txHash !== null && txHash !== void 0 ? txHash : hop.txHash) !== null && _a !== void 0 ? _a : response.hash;
1500
+ if (hop.route === 'UOA_TO_PUSH') {
1501
+ emitHopEvent(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_99](resolvedTxHash));
1502
+ return;
1503
+ }
1504
+ if (hop.route === 'UOA_TO_CEA') {
1505
+ emitHopEvent(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_299_99](hop.executionChain, resolvedTxHash));
1506
+ return;
1507
+ }
1508
+ if (hop.route === 'CEA_TO_PUSH') {
1509
+ emitHopEvent(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_399_99](hop.executionChain, resolvedTxHash));
1510
+ }
1511
+ };
1512
+ const buildCompletionResult = (success, failedAt) => {
1513
+ var _a, _b;
1514
+ const finalTxHash = (_b = (_a = [...hopInfos]
1515
+ .reverse()
1516
+ .find((hop) => hop.status === 'confirmed' && hop.txHash)) === null || _a === void 0 ? void 0 : _a.txHash) !== null && _b !== void 0 ? _b : response.hash;
1517
+ cascadeResponse.finalTxHash = finalTxHash;
1518
+ return Object.assign({ success, hops: hopInfos, finalTxHash, finalTxResponse: cascadeResponse }, (failedAt !== undefined ? { failedAt } : {}));
1519
+ };
1466
1520
  if (isMulti) {
1467
1521
  emitHopEvent(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_001](totalHops, chainLabels));
1468
1522
  }
@@ -1505,11 +1559,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1505
1559
  });
1506
1560
  emitHopEvent(hopHooks.timeout(hop.executionChain, Date.now() - startTime));
1507
1561
  emitCascadeTimeout(hop.hopIndex);
1508
- return {
1509
- success: false,
1510
- hops: hopInfos,
1511
- failedAt: hop.hopIndex,
1512
- };
1562
+ return buildCompletionResult(false, hop.hopIndex);
1513
1563
  }
1514
1564
  emitHopStart(hop.hopIndex);
1515
1565
  emitHopEvent(hopHooks.awaiting(hop.executionChain));
@@ -1550,7 +1600,12 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1550
1600
  hop.status = 'confirmed';
1551
1601
  hop.txHash = displayTxHash;
1552
1602
  hop.outboundDetails = userFacingOutboundDetails;
1553
- emitHopEvent(hopHooks.success(userFacingOutboundDetails));
1603
+ if (isMulti) {
1604
+ emitRouteIntermediateComplete(hop, displayTxHash);
1605
+ }
1606
+ else {
1607
+ emitHopEvent(hopHooks.success(userFacingOutboundDetails));
1608
+ }
1554
1609
  emitHopComplete(hop.hopIndex);
1555
1610
  cascadeProgressHook === null || cascadeProgressHook === void 0 ? void 0 : cascadeProgressHook({
1556
1611
  hopIndex: hop.hopIndex,
@@ -1581,11 +1636,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1581
1636
  status: 'failed',
1582
1637
  elapsed: Date.now() - startTime,
1583
1638
  });
1584
- return {
1585
- success: false,
1586
- hops: hopInfos,
1587
- failedAt: hop.hopIndex,
1588
- };
1639
+ return buildCompletionResult(false, hop.hopIndex);
1589
1640
  }
1590
1641
  }
1591
1642
  else {
@@ -1627,7 +1678,12 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1627
1678
  // guard above, so we only reach here with full details.
1628
1679
  if (matchedHop === null || matchedHop === void 0 ? void 0 : matchedHop.outboundDetails) {
1629
1680
  confirmedHops.add(event.hopIndex);
1630
- emitHopEvent(eventHooks.success(matchedHop.outboundDetails));
1681
+ if (isMulti) {
1682
+ emitRouteIntermediateComplete(matchedHop, event.txHash);
1683
+ }
1684
+ else {
1685
+ emitHopEvent(eventHooks.success(matchedHop.outboundDetails));
1686
+ }
1631
1687
  emitHopComplete(event.hopIndex);
1632
1688
  }
1633
1689
  }
@@ -1641,11 +1697,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1641
1697
  : `Outbound cascade failed at hop ${failedIdx}`;
1642
1698
  emitHopEvent((0, progress_route_hooks_1.pickWaitHooks)(failedHop === null || failedHop === void 0 ? void 0 : failedHop.route).failed((_d = failedHop === null || failedHop === void 0 ? void 0 : failedHop.executionChain) !== null && _d !== void 0 ? _d : '', failMsg));
1643
1699
  emitCascadeFailed(failedIdx, failMsg);
1644
- return {
1645
- success: false,
1646
- hops: hopInfos,
1647
- failedAt: failedIdx,
1648
- };
1700
+ return buildCompletionResult(false, failedIdx);
1649
1701
  }
1650
1702
  }
1651
1703
  return null;
@@ -1700,11 +1752,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1700
1752
  inboundHop.status = 'failed';
1701
1753
  emitHopEvent(hopHooks.timeout(inboundHop.executionChain, Date.now() - startTime));
1702
1754
  emitCascadeTimeout(inboundHop.hopIndex);
1703
- return {
1704
- success: false,
1705
- hops: hopInfos,
1706
- failedAt: inboundHop.hopIndex,
1707
- };
1755
+ return buildCompletionResult(false, inboundHop.hopIndex);
1708
1756
  }
1709
1757
  emitHopStart(inboundHop.hopIndex);
1710
1758
  emitHopEvent(hopHooks.awaiting(inboundHop.executionChain));
@@ -1763,11 +1811,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1763
1811
  txHash: failedDisplayTxHash,
1764
1812
  elapsed: Date.now() - startTime,
1765
1813
  });
1766
- return {
1767
- success: false,
1768
- hops: hopInfos,
1769
- failedAt: inboundHop.hopIndex,
1770
- };
1814
+ return buildCompletionResult(false, inboundHop.hopIndex);
1771
1815
  }
1772
1816
  const displayExternalTxHash = (_f = (0, helpers_1.toExternalTxHashDisplay)(sourceOutboundDetails.destinationChain, sourceOutboundDetails.externalTxHash)) !== null && _f !== void 0 ? _f : sourceOutboundDetails.externalTxHash;
1773
1817
  inboundHop.outboundDetails = Object.assign(Object.assign({}, sourceOutboundDetails), { externalTxHash: displayExternalTxHash });
@@ -1808,11 +1852,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1808
1852
  status: 'failed',
1809
1853
  elapsed: Date.now() - startTime,
1810
1854
  });
1811
- return {
1812
- success: false,
1813
- hops: hopInfos,
1814
- failedAt: inboundHop.hopIndex,
1815
- };
1855
+ return buildCompletionResult(false, inboundHop.hopIndex);
1816
1856
  }
1817
1857
  if (childInbound.status !== 'confirmed') {
1818
1858
  const failMsg = (_h = childInbound.errorMessage) !== null && _h !== void 0 ? _h : 'inbound execution failed on Push Chain';
@@ -1829,16 +1869,17 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1829
1869
  txHash: inboundHop.txHash,
1830
1870
  elapsed: Date.now() - startTime,
1831
1871
  });
1832
- return {
1833
- success: false,
1834
- hops: hopInfos,
1835
- failedAt: inboundHop.hopIndex,
1836
- };
1872
+ return buildCompletionResult(false, inboundHop.hopIndex);
1837
1873
  }
1838
1874
  inboundHop.status = 'confirmed';
1839
1875
  inboundHop.txHash =
1840
1876
  childInbound.pushTxHash || displayExternalTxHash;
1841
- emitHopEvent(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_399_01](inboundHop.executionChain, childInbound.pushTxHash));
1877
+ if (isMulti) {
1878
+ emitRouteIntermediateComplete(inboundHop, inboundHop.txHash);
1879
+ }
1880
+ else {
1881
+ emitHopEvent(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_399_01](inboundHop.executionChain, childInbound.pushTxHash));
1882
+ }
1842
1883
  emitHopComplete(inboundHop.hopIndex);
1843
1884
  cascadeProgressHook === null || cascadeProgressHook === void 0 ? void 0 : cascadeProgressHook({
1844
1885
  hopIndex: inboundHop.hopIndex,
@@ -1864,6 +1905,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1864
1905
  txHash: childInbound.pushTxHash,
1865
1906
  elapsed: Date.now() - startTime,
1866
1907
  });
1908
+ emitRouteIntermediateComplete(hop, childInbound.pushTxHash);
1867
1909
  emitHopComplete(hop.hopIndex);
1868
1910
  }
1869
1911
  }
@@ -1873,7 +1915,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1873
1915
  return childOutboundFailure;
1874
1916
  }
1875
1917
  emitCascadeSuccess();
1876
- return { success: true, hops: hopInfos };
1918
+ return buildCompletionResult(true);
1877
1919
  }
1878
1920
  catch (err) {
1879
1921
  const failedIdx = hopInfos.findIndex((h) => h.status !== 'confirmed');
@@ -1886,11 +1928,7 @@ function createCascadedBuilder(ctx, preparedTxs, callbacks, defaultEventHook) {
1886
1928
  else {
1887
1929
  emitCascadeFailed(failedAt, errMsg);
1888
1930
  }
1889
- return {
1890
- success: false,
1891
- hops: hopInfos,
1892
- failedAt,
1893
- };
1931
+ return buildCompletionResult(false, failedAt);
1894
1932
  }
1895
1933
  }),
1896
1934
  wait: (opts) => tslib_1.__awaiter(this, void 0, void 0, function* () { return cascadeResponse.waitForAll(opts); }),
@@ -48,9 +48,8 @@ function printLog(ctx, msg) {
48
48
  * Exceptions kept in the stream regardless of route:
49
49
  * - All UEA migration hooks.
50
50
  *
51
- * Separately, the intermediate Push-success markers 199-99-99 (R3) and
52
- * 299-99 (R2) are suppressed at `fanOut` in response-builder.ts — they're
53
- * internal transition signals, not consumer-facing spec events.
51
+ * Multihop-only intermediate success markers (199-99 / 299-99 / 399-99)
52
+ * are emitted by cascade tracking, not by the single-route wait path.
54
53
  */
55
54
  const R1_SUPPRESSED_IN_NON_R1 = new Set([
56
55
  progress_hook_types_1.PROGRESS_HOOK.SEND_TX_101,
@@ -69,7 +69,7 @@ function executeFundsOnly(ctx, execute, eventBuffer, getResponseCallbacks) {
69
69
  // ============================================================================
70
70
  function executeFundsOnlyEvm(ctx, execute, eventBuffer, transformFn, chain, rpcUrls, lockerContract, bridgeAmount, symbol) {
71
71
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
72
- var _a, _b;
72
+ var _a, _b, _c;
73
73
  const evmClient = (0, context_1.getOriginEvmClient)(ctx);
74
74
  const gatewayAddress = lockerContract;
75
75
  const tokenAddr = execute.funds.token.address;
@@ -96,8 +96,28 @@ function executeFundsOnlyEvm(ctx, execute, eventBuffer, transformFn, chain, rpcU
96
96
  nonce: nonce.toString(), deployed,
97
97
  }, (_, v) => typeof v === 'bigint' ? v.toString() : v, 2));
98
98
  const ueaBalanceForGas = yield ctx.pushClient.getBalance(ueaAddress);
99
- const nativeAmount = yield (0, gas_calculator_1.calculateNativeAmountForDeposit)(ctx, chain, BigInt(0), ueaBalanceForGas);
100
- (0, context_2.printLog)(ctx, `sendFunds — nativeAmount: ${nativeAmount.toString()}, ueaBalanceForGas: ${ueaBalanceForGas.toString()}`);
99
+ const gasEstimate = execute.gasLimit || BigInt(1e7);
100
+ const gasPrice = yield ctx.pushClient.getGasPrice();
101
+ const requiredGasFee = gasEstimate * gasPrice;
102
+ const requiredFunds = requiredGasFee + ((_c = execute.value) !== null && _c !== void 0 ? _c : BigInt(0));
103
+ let nativeAmount = yield (0, gas_calculator_1.calculateNativeAmountForDeposit)(ctx, chain, requiredFunds, ueaBalanceForGas);
104
+ // For EVM fee-locking, fixed-rate PC→USD sizing can underfund when the
105
+ // live WPC/native pool prices PC above the SDK's fallback price. Size the
106
+ // native deposit against the same Push Chain pool used by the gateway.
107
+ if (chain_1.CHAIN_INFO[chain].vm === enums_1.VM.EVM && requiredFunds > ueaBalanceForGas) {
108
+ const deficit = requiredFunds - ueaBalanceForGas;
109
+ const targetWpc = (deficit * BigInt(12)) / BigInt(10);
110
+ const originPrc20 = (0, helpers_1.getNativePRC20ForChain)(chain, ctx.pushNetwork);
111
+ const poolNativeAmount = yield (0, gas_calculator_1.estimateNativeForDesiredDeposit)(ctx, targetWpc, originPrc20);
112
+ if (poolNativeAmount > nativeAmount) {
113
+ (0, context_2.printLog)(ctx, `sendFunds — pool-based deposit sizing overrides fixed-rate estimate: fixedNative=${nativeAmount.toString()}, ` +
114
+ `poolNative=${poolNativeAmount.toString()}, requiredFunds=${requiredFunds.toString()}, ` +
115
+ `ueaBalance=${ueaBalanceForGas.toString()}`);
116
+ nativeAmount = poolNativeAmount;
117
+ }
118
+ }
119
+ (0, context_2.printLog)(ctx, `sendFunds — nativeAmount: ${nativeAmount.toString()}, ueaBalanceForGas: ${ueaBalanceForGas.toString()}, ` +
120
+ `requiredFunds: ${requiredFunds.toString()}`);
101
121
  (0, context_2.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_103_01);
102
122
  (0, context_2.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_103_02, ueaAddress, deployed);
103
123
  (0, context_2.printLog)(ctx, `UEA resolved: ${ueaAddress}, deployed: ${deployed}`);
@@ -13,8 +13,9 @@
13
13
  * - emits `SEND-TX-203-03` (INFO, sufficient) and lets the caller proceed;
14
14
  * - emits `SEND-TX-203-03` (WARNING, insufficient) and proceeds when
15
15
  * enforceGasCheck is false/omitted; or
16
- * - emits `SEND-TX-203-03` (ERROR, insufficient) + `SEND-TX-203-04` and
17
- * throws `InsufficientUEABalanceError` when enforceGasCheck is true.
16
+ * - emits `SEND-TX-203-03` (WARNING, insufficient) + `SEND-TX-203-04`
17
+ * (ERROR, terminal shortfall) and throws `InsufficientUEABalanceError`
18
+ * when enforceGasCheck is true.
18
19
  *
19
20
  * The helper is intentionally not "pure" — it emits hooks and may throw.
20
21
  * Callers fetch all balances (so the helper itself does no I/O).
@@ -14,8 +14,9 @@
14
14
  * - emits `SEND-TX-203-03` (INFO, sufficient) and lets the caller proceed;
15
15
  * - emits `SEND-TX-203-03` (WARNING, insufficient) and proceeds when
16
16
  * enforceGasCheck is false/omitted; or
17
- * - emits `SEND-TX-203-03` (ERROR, insufficient) + `SEND-TX-203-04` and
18
- * throws `InsufficientUEABalanceError` when enforceGasCheck is true.
17
+ * - emits `SEND-TX-203-03` (WARNING, insufficient) + `SEND-TX-203-04`
18
+ * (ERROR, terminal shortfall) and throws `InsufficientUEABalanceError`
19
+ * when enforceGasCheck is true.
19
20
  *
20
21
  * The helper is intentionally not "pure" — it emits hooks and may throw.
21
22
  * Callers fetch all balances (so the helper itself does no I/O).
@@ -10,7 +10,6 @@ import type { OutboundTxDetails } from '../orchestrator.types';
10
10
  import type { ProgressEvent } from '../../progress-hook/progress-hook.types';
11
11
  import { TransactionRoute } from '../route-detector';
12
12
  export type WaitHookSet = {
13
- intermediatePushOk?: (chain: string, pushTxHash: string) => ProgressEvent;
14
13
  awaiting: (chain: string) => ProgressEvent;
15
14
  polling: (chain: string, elapsedMs: number) => ProgressEvent;
16
15
  success: (details: OutboundTxDetails) => ProgressEvent;
@@ -17,7 +17,6 @@ const route_detector_1 = require("../route-detector");
17
17
  function pickWaitHooks(route) {
18
18
  if (route === route_detector_1.TransactionRoute.UOA_TO_CEA) {
19
19
  return {
20
- intermediatePushOk: (chain, txHash) => progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_299_99](chain, txHash),
21
20
  awaiting: (chain) => progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_209_01](chain),
22
21
  polling: (chain, elapsed) => progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_209_02](chain, elapsed),
23
22
  success: (details) => progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_299_01](details),
@@ -27,7 +26,6 @@ function pickWaitHooks(route) {
27
26
  }
28
27
  if (route === route_detector_1.TransactionRoute.CEA_TO_PUSH) {
29
28
  return {
30
- intermediatePushOk: (_chain, txHash) => progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_99_99](txHash),
31
29
  awaiting: (chain) => progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_309_01](chain),
32
30
  polling: (chain, elapsed) => progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_309_02](chain, elapsed),
33
31
  // For R3, the outbound-poll "success" is the source-chain CEA executing