@pushchain/core 5.1.17 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/lib/constants/abi/cea.evm.d.ts +52 -0
- package/src/lib/constants/abi/cea.evm.js +66 -1
- package/src/lib/constants/abi/prc20.evm.d.ts +117 -11
- package/src/lib/constants/abi/prc20.evm.js +38 -11
- package/src/lib/constants/abi/uea.evm.js +41 -0
- package/src/lib/constants/abi/universalGatewayPC.evm.d.ts +117 -1
- package/src/lib/constants/abi/universalGatewayPC.evm.js +40 -1
- package/src/lib/constants/abi/universalGatewayV0.json +1 -1
- package/src/lib/constants/chain.js +14 -14
- package/src/lib/constants/index.d.ts +1 -1
- package/src/lib/constants/index.js +2 -1
- package/src/lib/constants/selectors.d.ts +8 -0
- package/src/lib/constants/selectors.js +9 -1
- package/src/lib/constants/tokens.js +1 -0
- package/src/lib/formatters.d.ts +7 -0
- package/src/lib/formatters.js +46 -0
- package/src/lib/index.d.ts +2 -0
- package/src/lib/index.js +7 -1
- package/src/lib/orchestrator/internals/cascade.d.ts +8 -1
- package/src/lib/orchestrator/internals/cascade.js +593 -192
- package/src/lib/orchestrator/internals/error-decoder.d.ts +2 -6
- package/src/lib/orchestrator/internals/error-decoder.js +10 -10
- package/src/lib/orchestrator/internals/errors.d.ts +1 -1
- package/src/lib/orchestrator/internals/errors.js +8 -5
- package/src/lib/orchestrator/internals/execute-funds-only.js +3 -2
- package/src/lib/orchestrator/internals/execute-funds-payload.js +2 -1
- package/src/lib/orchestrator/internals/execute-standard.js +11 -10
- package/src/lib/orchestrator/internals/gas-calculator.d.ts +1 -0
- package/src/lib/orchestrator/internals/gas-calculator.js +91 -22
- package/src/lib/orchestrator/internals/helpers.d.ts +2 -1
- package/src/lib/orchestrator/internals/helpers.js +14 -11
- package/src/lib/orchestrator/internals/inbound-tracker.js +4 -2
- package/src/lib/orchestrator/internals/outbound-sync.d.ts +1 -0
- package/src/lib/orchestrator/internals/outbound-sync.js +140 -71
- package/src/lib/orchestrator/internals/pc-usd-oracle.d.ts +1 -1
- package/src/lib/orchestrator/internals/pc-usd-oracle.js +4 -3
- package/src/lib/orchestrator/internals/preflight.d.ts +2 -16
- package/src/lib/orchestrator/internals/preflight.js +2 -36
- package/src/lib/orchestrator/internals/push-chain-tx.js +5 -1
- package/src/lib/orchestrator/internals/response-builder.js +23 -7
- package/src/lib/orchestrator/internals/route-handlers.js +182 -227
- package/src/lib/orchestrator/internals/signing.js +7 -2
- package/src/lib/orchestrator/internals/svm-helpers.js +3 -3
- package/src/lib/orchestrator/internals/svm-rent.d.ts +42 -9
- package/src/lib/orchestrator/internals/svm-rent.js +148 -14
- package/src/lib/orchestrator/internals/tx-transformer.js +5 -2
- package/src/lib/orchestrator/max-pc-for-gas.d.ts +60 -0
- package/src/lib/orchestrator/max-pc-for-gas.js +66 -0
- package/src/lib/orchestrator/orchestrator.d.ts +8 -1
- package/src/lib/orchestrator/orchestrator.js +40 -2
- package/src/lib/orchestrator/orchestrator.types.d.ts +35 -23
- package/src/lib/orchestrator/payload-builders.d.ts +7 -6
- package/src/lib/orchestrator/payload-builders.js +18 -6
- package/src/lib/progress-hook/progress-hook.js +39 -38
- package/src/lib/push-chain/push-chain.d.ts +11 -1
- package/src/lib/push-chain/push-chain.js +2 -2
- package/src/lib/universal-tx-detector/cascade.js +14 -4
- package/src/lib/universal-tx-detector/child-inbounds.js +9 -1
- package/src/lib/universal-tx-detector/detector.js +9 -3
- package/src/lib/universal-tx-detector/events.d.ts +3 -1
- package/src/lib/universal-tx-detector/events.js +3 -1
- package/src/lib/universal-tx-detector/normalize.d.ts +42 -0
- package/src/lib/universal-tx-detector/normalize.js +127 -0
- package/src/lib/universal-tx-detector/svm-events.d.ts +1 -1
- package/src/lib/universal-tx-detector/svm-events.js +1 -1
- package/src/lib/utils/external-tx-hash.d.ts +37 -0
- package/src/lib/utils/external-tx-hash.js +62 -0
|
@@ -11,11 +11,11 @@ exports.waitForOutboundTx = waitForOutboundTx;
|
|
|
11
11
|
exports.waitForAllOutboundTxsV2 = waitForAllOutboundTxsV2;
|
|
12
12
|
const tslib_1 = require("tslib");
|
|
13
13
|
const viem_1 = require("viem");
|
|
14
|
-
const bs58_1 = require("../../internal/bs58");
|
|
15
14
|
const chain_1 = require("../../constants/chain");
|
|
16
15
|
const enums_1 = require("../../constants/enums");
|
|
17
16
|
const types_1 = require("../../generated/uexecutor/v1/types");
|
|
18
17
|
const types_2 = require("../../generated/uexecutor/v2/types");
|
|
18
|
+
const formatters_1 = require("../../formatters");
|
|
19
19
|
const context_1 = require("./context");
|
|
20
20
|
const helpers_1 = require("./helpers");
|
|
21
21
|
const outbound_tracker_1 = require("./outbound-tracker");
|
|
@@ -142,8 +142,8 @@ function verifyExternalEvmReceipt(ctx, destinationChain, externalTxHash) {
|
|
|
142
142
|
*/
|
|
143
143
|
function waitForOutboundTx(ctx_1, pushChainTxHash_1) {
|
|
144
144
|
return tslib_1.__awaiter(this, arguments, void 0, function* (ctx, pushChainTxHash, options = {}) {
|
|
145
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
146
|
-
const { initialWaitMs = exports.OUTBOUND_INITIAL_WAIT_MS, pollingIntervalMs = exports.OUTBOUND_POLL_INTERVAL_MS, timeout = exports.OUTBOUND_MAX_TIMEOUT_MS, progressHook, _resolvedSubTxId, _expectedDestinationChain, } = options;
|
|
145
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
146
|
+
const { initialWaitMs = exports.OUTBOUND_INITIAL_WAIT_MS, pollingIntervalMs = exports.OUTBOUND_POLL_INTERVAL_MS, timeout = exports.OUTBOUND_MAX_TIMEOUT_MS, progressHook, _resolvedSubTxId, _expectedDestinationChain, _outboundIndex, } = options;
|
|
147
147
|
// Terminal failure states — fail fast instead of polling until timeout
|
|
148
148
|
const TERMINAL_FAILURE_STATES = new Set([
|
|
149
149
|
types_1.UniversalTxStatus.OUTBOUND_FAILED,
|
|
@@ -195,20 +195,54 @@ function waitForOutboundTx(ctx_1, pushChainTxHash_1) {
|
|
|
195
195
|
const statusNum = (_b = utxResponse === null || utxResponse === void 0 ? void 0 : utxResponse.universalTx) === null || _b === void 0 ? void 0 : _b.universalStatus;
|
|
196
196
|
const statusName = (_c = types_1.UniversalTxStatus[statusNum]) !== null && _c !== void 0 ? _c : statusNum;
|
|
197
197
|
const outbounds = ((_d = utxResponse === null || utxResponse === void 0 ? void 0 : utxResponse.universalTx) === null || _d === void 0 ? void 0 : _d.outboundTx) || [];
|
|
198
|
-
|
|
198
|
+
const firstOutbound = outbounds[0];
|
|
199
|
+
const firstOutboundChain = (firstOutbound === null || firstOutbound === void 0 ? void 0 : firstOutbound.destinationChain)
|
|
200
|
+
? (0, helpers_1.chainFromNamespace)(firstOutbound.destinationChain)
|
|
201
|
+
: undefined;
|
|
202
|
+
const firstDisplayTxHash = (_h = (_f = (0, helpers_1.toExternalTxHashDisplay)(firstOutboundChain !== null && firstOutboundChain !== void 0 ? firstOutboundChain : undefined, (_e = firstOutbound === null || firstOutbound === void 0 ? void 0 : firstOutbound.observedTx) === null || _e === void 0 ? void 0 : _e.txHash)) !== null && _f !== void 0 ? _f : (_g = firstOutbound === null || firstOutbound === void 0 ? void 0 : firstOutbound.observedTx) === null || _g === void 0 ? void 0 : _g.txHash) !== null && _h !== void 0 ? _h : '';
|
|
203
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Poll #${pollCount} | status: ${statusNum} (${statusName}) | outboundTx count: ${outbounds.length} | first txHash: '${firstDisplayTxHash}' | first dest: '${(firstOutbound === null || firstOutbound === void 0 ? void 0 : firstOutbound.destinationChain) || ''}'`);
|
|
199
204
|
// Check for terminal failure states — fail fast
|
|
200
205
|
if (TERMINAL_FAILURE_STATES.has(statusNum)) {
|
|
201
206
|
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Terminal failure state: ${statusName}`);
|
|
202
207
|
progressHook === null || progressHook === void 0 ? void 0 : progressHook({ status: 'failed', elapsed: Date.now() - startTime });
|
|
203
208
|
throw new OutboundFailedError(`Outbound transaction failed with status ${statusName}. Push Chain TX: ${pushChainTxHash}.`, pushChainTxHash);
|
|
204
209
|
}
|
|
205
|
-
|
|
210
|
+
const pcTxs = ((_j = utxResponse === null || utxResponse === void 0 ? void 0 : utxResponse.universalTx) === null || _j === void 0 ? void 0 : _j.pcTx) || [];
|
|
211
|
+
const failedPcTx = pcTxs.find((pcTx) => {
|
|
212
|
+
const status = String(pcTx.status || '').toUpperCase();
|
|
213
|
+
return status === 'FAILED' || Boolean(pcTx.errorMsg);
|
|
214
|
+
});
|
|
215
|
+
if (failedPcTx) {
|
|
216
|
+
const failedTxHash = failedPcTx.txHash || pushChainTxHash;
|
|
217
|
+
const reason = failedPcTx.errorMsg
|
|
218
|
+
? (0, formatters_1.normalizePcInsufficientFundsError)(failedPcTx.errorMsg)
|
|
219
|
+
: 'Push Chain execution failed';
|
|
220
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Push Chain execution failed before outbound emission: ${reason}`);
|
|
221
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({ status: 'failed', elapsed: Date.now() - startTime });
|
|
222
|
+
throw new OutboundFailedError(`Push Chain execution failed before outbound emission: ${reason}. Push Chain TX: ${failedTxHash}.`, pushChainTxHash, undefined, failedPcTx.txHash || undefined);
|
|
223
|
+
}
|
|
224
|
+
// Iterate V2 outbound array. For cascade tracking, multiple outbound
|
|
225
|
+
// entries can target the same destination chain (for example R2 BSC
|
|
226
|
+
// followed by R3 BSC -> Push). `_outboundIndex` disambiguates those
|
|
227
|
+
// same-chain entries by order after `_expectedDestinationChain` filtering.
|
|
228
|
+
let matchingOutboundIndex = 0;
|
|
206
229
|
for (const ob of outbounds) {
|
|
230
|
+
// If a destination chain filter is set, skip outbound entries that don't match.
|
|
231
|
+
if (_expectedDestinationChain && ob.destinationChain !== _expectedDestinationChain) {
|
|
232
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Poll #${pollCount} | outbound chain '${ob.destinationChain}' does not match expected '${_expectedDestinationChain}', skipping`);
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
const currentOutboundIndex = matchingOutboundIndex;
|
|
236
|
+
matchingOutboundIndex += 1;
|
|
237
|
+
if (_outboundIndex !== undefined && currentOutboundIndex !== _outboundIndex) {
|
|
238
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Poll #${pollCount} | outbound index ${currentOutboundIndex} for '${ob.destinationChain}' does not match expected index ${_outboundIndex}, skipping`);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
207
241
|
// Fail fast on per-outbound REVERTED status
|
|
208
242
|
if (ob.outboundStatus === types_2.OutboundStatus.REVERTED) {
|
|
209
243
|
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Outbound to ${ob.destinationChain} REVERTED`);
|
|
210
244
|
progressHook === null || progressHook === void 0 ? void 0 : progressHook({ status: 'failed', elapsed: Date.now() - startTime });
|
|
211
|
-
throw new OutboundFailedError(`Outbound to ${ob.destinationChain} reverted: ${((
|
|
245
|
+
throw new OutboundFailedError(`Outbound to ${ob.destinationChain} reverted: ${((_k = ob.observedTx) === null || _k === void 0 ? void 0 : _k.errorMsg) || 'Unknown'}. Push Chain TX: ${pushChainTxHash}.`, pushChainTxHash, ob.destinationChain, (_l = ob.observedTx) === null || _l === void 0 ? void 0 : _l.txHash);
|
|
212
246
|
}
|
|
213
247
|
// FOUND gating logic:
|
|
214
248
|
// 1. Primary path — cosmos has transitioned to OBSERVED (the
|
|
@@ -218,12 +252,7 @@ function waitForOutboundTx(ctx_1, pushChainTxHash_1) {
|
|
|
218
252
|
// destination chain's own RPC: if its receipt is success,
|
|
219
253
|
// treat as FOUND; if reverted, throw OutboundFailedError.
|
|
220
254
|
// Pending receipts keep polling.
|
|
221
|
-
if ((
|
|
222
|
-
// If a destination chain filter is set, skip outbound entries that don't match
|
|
223
|
-
if (_expectedDestinationChain && ob.destinationChain !== _expectedDestinationChain) {
|
|
224
|
-
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Poll #${pollCount} | outbound chain '${ob.destinationChain}' does not match expected '${_expectedDestinationChain}', skipping`);
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
255
|
+
if ((_m = ob.observedTx) === null || _m === void 0 ? void 0 : _m.txHash) {
|
|
227
256
|
const chain = (0, helpers_1.chainFromNamespace)(ob.destinationChain);
|
|
228
257
|
if (!chain)
|
|
229
258
|
continue;
|
|
@@ -232,7 +261,7 @@ function waitForOutboundTx(ctx_1, pushChainTxHash_1) {
|
|
|
232
261
|
// Tiebreaker: ask the destination-chain RPC directly.
|
|
233
262
|
const verdict = yield verifyExternalEvmReceipt(ctx, chain, ob.observedTx.txHash);
|
|
234
263
|
if (verdict === 'reverted') {
|
|
235
|
-
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Source-chain RPC reports REVERTED for ${ob.destinationChain} tx ${ob.observedTx.txHash} (cosmos still ${(
|
|
264
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Source-chain RPC reports REVERTED for ${ob.destinationChain} tx ${ob.observedTx.txHash} (cosmos still ${(_o = types_1.UniversalTxStatus[statusNum]) !== null && _o !== void 0 ? _o : statusNum})`);
|
|
236
265
|
progressHook === null || progressHook === void 0 ? void 0 : progressHook({ status: 'failed', elapsed: Date.now() - startTime });
|
|
237
266
|
throw new OutboundFailedError(`Outbound to ${ob.destinationChain} reverted on source-chain RPC (tx: ${ob.observedTx.txHash}). Push Chain TX: ${pushChainTxHash}.`, pushChainTxHash, ob.destinationChain, ob.observedTx.txHash);
|
|
238
267
|
}
|
|
@@ -240,24 +269,26 @@ function waitForOutboundTx(ctx_1, pushChainTxHash_1) {
|
|
|
240
269
|
// 'pending' or 'unsupported' — keep polling, cosmos will catch up.
|
|
241
270
|
continue;
|
|
242
271
|
}
|
|
243
|
-
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Source-chain RPC tiebreaker: ${chain} tx ${ob.observedTx.txHash} succeeded; treating as FOUND despite cosmos status ${(
|
|
272
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] Source-chain RPC tiebreaker: ${chain} tx ${ob.observedTx.txHash} succeeded; treating as FOUND despite cosmos status ${(_p = types_1.UniversalTxStatus[statusNum]) !== null && _p !== void 0 ? _p : statusNum}`);
|
|
244
273
|
}
|
|
245
274
|
{
|
|
246
|
-
const explorerBaseUrl = (
|
|
247
|
-
const isSvm = ((
|
|
248
|
-
|
|
249
|
-
let displayTxHash = ob.observedTx.txHash;
|
|
275
|
+
const explorerBaseUrl = (_q = chain_1.CHAIN_INFO[chain]) === null || _q === void 0 ? void 0 : _q.explorerUrl;
|
|
276
|
+
const isSvm = ((_r = chain_1.CHAIN_INFO[chain]) === null || _r === void 0 ? void 0 : _r.vm) === enums_1.VM.SVM;
|
|
277
|
+
const displayTxHash = (_s = (0, helpers_1.toExternalTxHashDisplay)(chain, ob.observedTx.txHash)) !== null && _s !== void 0 ? _s : ob.observedTx.txHash;
|
|
250
278
|
let explorerUrl = '';
|
|
251
|
-
if (isSvm
|
|
252
|
-
const bytes = new Uint8Array(Buffer.from(ob.observedTx.txHash.slice(2), 'hex'));
|
|
253
|
-
displayTxHash = bs58_1.bs58.encode(Buffer.from(bytes));
|
|
279
|
+
if (isSvm) {
|
|
254
280
|
const cluster = chain === enums_1.CHAIN.SOLANA_DEVNET ? '?cluster=devnet'
|
|
255
281
|
: chain === enums_1.CHAIN.SOLANA_TESTNET ? '?cluster=testnet' : '';
|
|
256
282
|
explorerUrl = explorerBaseUrl ? `${explorerBaseUrl}/tx/${displayTxHash}${cluster}` : '';
|
|
257
283
|
}
|
|
258
284
|
else {
|
|
259
|
-
explorerUrl = explorerBaseUrl ? `${explorerBaseUrl}/tx/${
|
|
285
|
+
explorerUrl = explorerBaseUrl ? `${explorerBaseUrl}/tx/${displayTxHash}` : '';
|
|
260
286
|
}
|
|
287
|
+
// OutboundTxDetails carries the raw `0x`-hex form so internal
|
|
288
|
+
// consumers (R3 inbound tracker in response-builder.ts:786 →
|
|
289
|
+
// findChildUtxIdFromExternalTx → Cosmos query) keep working.
|
|
290
|
+
// The base58 display form is applied at every user-facing
|
|
291
|
+
// boundary via `toExternalTxHashDisplay` (helpers.ts).
|
|
261
292
|
const details = {
|
|
262
293
|
externalTxHash: ob.observedTx.txHash,
|
|
263
294
|
destinationChain: chain,
|
|
@@ -266,7 +297,7 @@ function waitForOutboundTx(ctx_1, pushChainTxHash_1) {
|
|
|
266
297
|
amount: ob.amount,
|
|
267
298
|
assetAddr: ob.externalAssetAddr,
|
|
268
299
|
};
|
|
269
|
-
(0, context_1.printLog)(ctx, `[waitForOutboundTx] FOUND on poll #${pollCount} | elapsed: ${Date.now() - startTime}ms | externalTxHash: ${
|
|
300
|
+
(0, context_1.printLog)(ctx, `[waitForOutboundTx] FOUND on poll #${pollCount} | elapsed: ${Date.now() - startTime}ms | externalTxHash: ${displayTxHash}`);
|
|
270
301
|
progressHook === null || progressHook === void 0 ? void 0 : progressHook({ status: 'found', elapsed: Date.now() - startTime });
|
|
271
302
|
return details;
|
|
272
303
|
}
|
|
@@ -302,8 +333,8 @@ function waitForOutboundTx(ctx_1, pushChainTxHash_1) {
|
|
|
302
333
|
*/
|
|
303
334
|
function waitForAllOutboundTxsV2(ctx, pushChainTxHash, outboundHops, options) {
|
|
304
335
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
305
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
306
|
-
const { initialWaitMs, pollingIntervalMs, timeout, progressHook } = options;
|
|
336
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
337
|
+
const { initialWaitMs, pollingIntervalMs, timeout, progressHook, _resolvedSubTxId, } = options;
|
|
307
338
|
const startTime = Date.now();
|
|
308
339
|
// Build a map: CAIP-2 namespace -> hop(s) for matching outbound entries
|
|
309
340
|
const chainToHops = new Map();
|
|
@@ -341,7 +372,11 @@ function waitForAllOutboundTxsV2(ctx, pushChainTxHash, outboundHops, options) {
|
|
|
341
372
|
});
|
|
342
373
|
}
|
|
343
374
|
// Extract sub-tx ID for V2 query
|
|
344
|
-
let cachedQueryId
|
|
375
|
+
let cachedQueryId = _resolvedSubTxId
|
|
376
|
+
? _resolvedSubTxId.startsWith('0x')
|
|
377
|
+
? _resolvedSubTxId.slice(2)
|
|
378
|
+
: _resolvedSubTxId
|
|
379
|
+
: undefined;
|
|
345
380
|
let pollCount = 0;
|
|
346
381
|
let consecutiveErrors = 0;
|
|
347
382
|
const MAX_CONSECUTIVE_ERRORS = 10;
|
|
@@ -364,67 +399,101 @@ function waitForAllOutboundTxsV2(ctx, pushChainTxHash, outboundHops, options) {
|
|
|
364
399
|
const statusName = (_a = types_1.UniversalTxStatus[statusNum]) !== null && _a !== void 0 ? _a : statusNum;
|
|
365
400
|
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] Poll #${pollCount} | status: ${statusNum} (${statusName}) | outboundTx count: ${(_c = (_b = utx === null || utx === void 0 ? void 0 : utx.outboundTx) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0}`);
|
|
366
401
|
if ((_d = utx === null || utx === void 0 ? void 0 : utx.outboundTx) === null || _d === void 0 ? void 0 : _d.length) {
|
|
402
|
+
const outboundOrdinalByChain = new Map();
|
|
367
403
|
for (const ob of utx.outboundTx) {
|
|
368
404
|
const destChain = ob.destinationChain;
|
|
369
405
|
const hopsForChain = chainToHops.get(destChain);
|
|
370
406
|
if (!hopsForChain)
|
|
371
407
|
continue;
|
|
372
|
-
const
|
|
373
|
-
|
|
408
|
+
const outboundOrdinal = (_e = outboundOrdinalByChain.get(destChain)) !== null && _e !== void 0 ? _e : 0;
|
|
409
|
+
outboundOrdinalByChain.set(destChain, outboundOrdinal + 1);
|
|
410
|
+
const targetHop = hopsForChain[outboundOrdinal];
|
|
411
|
+
if (!targetHop ||
|
|
412
|
+
targetHop.status === 'confirmed' ||
|
|
413
|
+
targetHop.status === 'failed') {
|
|
374
414
|
continue;
|
|
375
|
-
// Fail fast on per-outbound REVERTED
|
|
376
|
-
if (ob.outboundStatus === types_2.OutboundStatus.REVERTED) {
|
|
377
|
-
for (const hop of unconfirmedForChain) {
|
|
378
|
-
hop.status = 'failed';
|
|
379
|
-
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] Outbound to ${destChain} REVERTED | hop ${hop.hopIndex} | error: ${((_e = ob.observedTx) === null || _e === void 0 ? void 0 : _e.errorMsg) || 'Unknown'}`);
|
|
380
|
-
progressHook === null || progressHook === void 0 ? void 0 : progressHook({
|
|
381
|
-
hopIndex: hop.hopIndex,
|
|
382
|
-
route: hop.route,
|
|
383
|
-
chain: hop.executionChain,
|
|
384
|
-
status: 'failed',
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
|
-
return { success: false, failedAt: unconfirmedForChain[0].hopIndex };
|
|
388
415
|
}
|
|
389
|
-
// Check for OBSERVED with txHash
|
|
390
416
|
const externalTxHash = (_f = ob.observedTx) === null || _f === void 0 ? void 0 : _f.txHash;
|
|
391
|
-
|
|
417
|
+
const hasObservedTxHash = !!externalTxHash && externalTxHash !== 'EMPTY';
|
|
418
|
+
const observedFailure = hasObservedTxHash &&
|
|
419
|
+
((_g = ob.observedTx) === null || _g === void 0 ? void 0 : _g.success) === false &&
|
|
420
|
+
Boolean(((_h = ob.observedTx) === null || _h === void 0 ? void 0 : _h.errorMsg) ||
|
|
421
|
+
ob.abortReason ||
|
|
422
|
+
ob.outboundStatus >= types_2.OutboundStatus.REVERTED);
|
|
423
|
+
// Fail fast on per-outbound REVERTED or observed destination failure.
|
|
424
|
+
if (ob.outboundStatus === types_2.OutboundStatus.REVERTED || observedFailure) {
|
|
425
|
+
targetHop.status = 'failed';
|
|
426
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] Outbound to ${destChain} REVERTED | outboundIndex ${outboundOrdinal} | hop ${targetHop.hopIndex} | error: ${ob.abortReason || ((_j = ob.observedTx) === null || _j === void 0 ? void 0 : _j.errorMsg) || 'Unknown'}`);
|
|
427
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({
|
|
428
|
+
hopIndex: targetHop.hopIndex,
|
|
429
|
+
route: targetHop.route,
|
|
430
|
+
chain: targetHop.executionChain,
|
|
431
|
+
status: 'failed',
|
|
432
|
+
});
|
|
433
|
+
return { success: false, failedAt: targetHop.hopIndex };
|
|
434
|
+
}
|
|
435
|
+
// Check for observed tx hash. Cosmos may lag the status transition,
|
|
436
|
+
// so EVM destinations are verified against the destination receipt.
|
|
437
|
+
if (hasObservedTxHash && externalTxHash) {
|
|
392
438
|
const chain = (0, helpers_1.chainFromNamespace)(destChain);
|
|
439
|
+
if (!chain)
|
|
440
|
+
continue;
|
|
441
|
+
const isCosmosObserved = ob.outboundStatus === types_2.OutboundStatus.OBSERVED;
|
|
442
|
+
if (!isCosmosObserved) {
|
|
443
|
+
const verdict = yield verifyExternalEvmReceipt(ctx, chain, externalTxHash);
|
|
444
|
+
if (verdict === 'reverted') {
|
|
445
|
+
targetHop.status = 'failed';
|
|
446
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] Source-chain RPC reports REVERTED for ${destChain} tx ${externalTxHash} | outboundIndex ${outboundOrdinal} | hop ${targetHop.hopIndex}`);
|
|
447
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({
|
|
448
|
+
hopIndex: targetHop.hopIndex,
|
|
449
|
+
route: targetHop.route,
|
|
450
|
+
chain: targetHop.executionChain,
|
|
451
|
+
status: 'failed',
|
|
452
|
+
});
|
|
453
|
+
return { success: false, failedAt: targetHop.hopIndex };
|
|
454
|
+
}
|
|
455
|
+
if (verdict !== 'success') {
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
// Build the display form for SVM (base58) used in `hop.txHash` /
|
|
460
|
+
// `hop.outboundDetails.externalTxHash` / the progressHook event —
|
|
461
|
+
// these are USER-FACING. The internal raw-hex form stays only
|
|
462
|
+
// inside this function; it's not exposed to consumers from the
|
|
463
|
+
// cascade path (cascade.ts doesn't call findChildUtxIdFromExternalTx
|
|
464
|
+
// for the cascade outbound hash).
|
|
465
|
+
const displayTxHash = (_k = (0, helpers_1.toExternalTxHashDisplay)(chain !== null && chain !== void 0 ? chain : undefined, externalTxHash)) !== null && _k !== void 0 ? _k : externalTxHash;
|
|
393
466
|
let explorerUrl = '';
|
|
394
467
|
if (chain && externalTxHash) {
|
|
395
|
-
const explorerBaseUrl = (
|
|
396
|
-
const isSvm = ((
|
|
397
|
-
if (isSvm
|
|
398
|
-
const bytes = new Uint8Array(Buffer.from(externalTxHash.slice(2), 'hex'));
|
|
399
|
-
const base58Hash = bs58_1.bs58.encode(Buffer.from(bytes));
|
|
468
|
+
const explorerBaseUrl = (_l = chain_1.CHAIN_INFO[chain]) === null || _l === void 0 ? void 0 : _l.explorerUrl;
|
|
469
|
+
const isSvm = ((_m = chain_1.CHAIN_INFO[chain]) === null || _m === void 0 ? void 0 : _m.vm) === enums_1.VM.SVM;
|
|
470
|
+
if (isSvm) {
|
|
400
471
|
const cluster = chain === enums_1.CHAIN.SOLANA_DEVNET ? '?cluster=devnet'
|
|
401
472
|
: chain === enums_1.CHAIN.SOLANA_TESTNET ? '?cluster=testnet' : '';
|
|
402
|
-
explorerUrl = explorerBaseUrl ? `${explorerBaseUrl}/tx/${
|
|
473
|
+
explorerUrl = explorerBaseUrl ? `${explorerBaseUrl}/tx/${displayTxHash}${cluster}` : '';
|
|
403
474
|
}
|
|
404
475
|
else {
|
|
405
|
-
explorerUrl = explorerBaseUrl ? `${explorerBaseUrl}/tx/${
|
|
476
|
+
explorerUrl = explorerBaseUrl ? `${explorerBaseUrl}/tx/${displayTxHash}` : '';
|
|
406
477
|
}
|
|
407
478
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
});
|
|
427
|
-
}
|
|
479
|
+
targetHop.status = 'confirmed';
|
|
480
|
+
targetHop.txHash = displayTxHash;
|
|
481
|
+
targetHop.outboundDetails = {
|
|
482
|
+
externalTxHash: displayTxHash,
|
|
483
|
+
destinationChain: chain || targetHop.executionChain,
|
|
484
|
+
explorerUrl,
|
|
485
|
+
recipient: ob.recipient,
|
|
486
|
+
amount: ob.amount,
|
|
487
|
+
assetAddr: ob.externalAssetAddr,
|
|
488
|
+
};
|
|
489
|
+
(0, context_1.printLog)(ctx, `[waitForAllOutboundTxsV2] FOUND outbound for ${destChain} | outboundIndex ${outboundOrdinal} | hop ${targetHop.hopIndex} | externalTxHash: ${displayTxHash}`);
|
|
490
|
+
progressHook === null || progressHook === void 0 ? void 0 : progressHook({
|
|
491
|
+
hopIndex: targetHop.hopIndex,
|
|
492
|
+
route: targetHop.route,
|
|
493
|
+
chain: targetHop.executionChain,
|
|
494
|
+
status: 'confirmed',
|
|
495
|
+
txHash: displayTxHash,
|
|
496
|
+
});
|
|
428
497
|
}
|
|
429
498
|
}
|
|
430
499
|
}
|
|
@@ -439,7 +508,7 @@ function waitForAllOutboundTxsV2(ctx, pushChainTxHash, outboundHops, options) {
|
|
|
439
508
|
if (statusNum === types_1.UniversalTxStatus.PC_EXECUTED_SUCCESS) {
|
|
440
509
|
const stillUnresolved = outboundHops.filter((h) => h.status !== 'confirmed');
|
|
441
510
|
if (stillUnresolved.length > 0) {
|
|
442
|
-
const hasPendingOutbound = (
|
|
511
|
+
const hasPendingOutbound = (_o = utx === null || utx === void 0 ? void 0 : utx.outboundTx) === null || _o === void 0 ? void 0 : _o.some((ob) => {
|
|
443
512
|
var _a;
|
|
444
513
|
return ob.outboundStatus === types_2.OutboundStatus.PENDING &&
|
|
445
514
|
(!((_a = ob.observedTx) === null || _a === void 0 ? void 0 : _a.txHash) || ob.observedTx.txHash === 'EMPTY');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CHAIN } from '../../constants/enums';
|
|
2
2
|
import type { OrchestratorContext } from './context';
|
|
3
|
-
type StableKey = 'USDT_ETH' | 'USDT_ARB' | 'USDT_BASE' | 'USDT_BNB' | 'USDT_SOL';
|
|
3
|
+
type StableKey = 'USDT_ETH' | 'USDT_ARB' | 'USDT_BASE' | 'USDT_BNB' | 'USDC_BNB' | 'USDT_SOL';
|
|
4
4
|
/**
|
|
5
5
|
* Get $PC/USD price (8 decimals) for the given origin chain's route.
|
|
6
6
|
* Returns 0 on any failure — caller is expected to fall back to
|
|
@@ -15,8 +15,9 @@ const tslib_1 = require("tslib");
|
|
|
15
15
|
* - Ethereum / Arbitrum / Base / BNB → WPC/USDT.<route>
|
|
16
16
|
* - Solana → WPC/USDT.sol
|
|
17
17
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
18
|
+
* Confirmed testnet pool-token addresses are sourced from
|
|
19
|
+
* SYNTHETIC_PUSH_ERC20. Flip ORIGIN_TO_STABLE if a route should use USDC
|
|
20
|
+
* instead of USDT.
|
|
20
21
|
*
|
|
21
22
|
* Returns price in **8 decimals** (USD per 1 WPC) to match the convention
|
|
22
23
|
* used by PriceFetch.getPrice.
|
|
@@ -153,7 +154,7 @@ function getPcUsdPrice(ctx, originChain) {
|
|
|
153
154
|
const universalCoreAddress = yield ctx.pushClient.readContract({
|
|
154
155
|
address: gatewayPcAddress,
|
|
155
156
|
abi: abi_1.UNIVERSAL_GATEWAY_PC,
|
|
156
|
-
functionName: '
|
|
157
|
+
functionName: 'universalCore',
|
|
157
158
|
args: [],
|
|
158
159
|
});
|
|
159
160
|
const [wpcAddress, factoryAddress, defaultFeeTier] = yield Promise.all([
|
|
@@ -23,7 +23,7 @@ import { type PreflightPathTag } from './errors';
|
|
|
23
23
|
export interface RunPreflightOpts {
|
|
24
24
|
ctx: OrchestratorContext;
|
|
25
25
|
ueaAddress: `0x${string}`;
|
|
26
|
-
/** Effective UEA balance in wei
|
|
26
|
+
/** Effective UEA balance in native PC wei (already includes fresh-wallet prediction). */
|
|
27
27
|
ueaBalance: bigint;
|
|
28
28
|
/** Buffered pool quote (pre-clamp) — what the SDK would actually attempt. */
|
|
29
29
|
requiredValue: bigint;
|
|
@@ -36,30 +36,16 @@ export interface RunPreflightOpts {
|
|
|
36
36
|
prc20Balance?: bigint;
|
|
37
37
|
/** Cascade-only: identifies which segment failed. */
|
|
38
38
|
segmentIndex?: number;
|
|
39
|
-
/**
|
|
40
|
-
* Per-call opt-out (`params.options.allowUnderfundedSwap`). When `true`,
|
|
41
|
-
* pre-flight logs the shortfall but does NOT fire 203-04 or throw —
|
|
42
|
-
* caller can fall back to the legacy clamp-and-refund branch.
|
|
43
|
-
*/
|
|
44
|
-
allowUnderfundedSwap?: boolean;
|
|
45
39
|
}
|
|
46
40
|
export type PreflightResult = {
|
|
47
41
|
ok: true;
|
|
48
42
|
/** What `nativeValueForGas` should be (== requiredValue when sufficient). */
|
|
49
43
|
adjustedValue: bigint;
|
|
50
|
-
} | {
|
|
51
|
-
ok: false;
|
|
52
|
-
/** Set when allowUnderfundedSwap=true: the legacy clamped value. */
|
|
53
|
-
legacyClampedValue: bigint;
|
|
54
44
|
};
|
|
55
45
|
/**
|
|
56
46
|
* Pre-flight check. PRC-20 balance is checked before the native check —
|
|
57
47
|
* a missing burn token fails before the gas-balance check, so the user
|
|
58
|
-
* sees the actionable PRC-20 shortfall instead of a stale
|
|
59
|
-
*
|
|
60
|
-
* Returns a result object instead of throwing for the legacy opt-out
|
|
61
|
-
* path. The throw happens here (not in the caller) for the default
|
|
62
|
-
* `allowUnderfundedSwap=false` case so all 6 paths share one throw site.
|
|
48
|
+
* sees the actionable PRC-20 shortfall instead of a stale native PC error.
|
|
63
49
|
*/
|
|
64
50
|
export declare function runPreflight(opts: RunPreflightOpts): PreflightResult;
|
|
65
51
|
/**
|
|
@@ -26,31 +26,13 @@ exports.maybeFireSvmWarnThreshold = maybeFireSvmWarnThreshold;
|
|
|
26
26
|
const context_1 = require("./context");
|
|
27
27
|
const progress_hook_types_1 = require("../../progress-hook/progress-hook.types");
|
|
28
28
|
const errors_1 = require("./errors");
|
|
29
|
-
/**
|
|
30
|
-
* Internal: compute the legacy clamp value (matches the pre-existing
|
|
31
|
-
* branches in route-handlers.ts:643-659 / :968-980 / :1396-1412).
|
|
32
|
-
* Returned only when `allowUnderfundedSwap=true`.
|
|
33
|
-
*/
|
|
34
|
-
function legacyClamp(ueaBalance, requiredValue, gasReserve) {
|
|
35
|
-
if (ueaBalance >= requiredValue + gasReserve)
|
|
36
|
-
return requiredValue;
|
|
37
|
-
if (ueaBalance > gasReserve)
|
|
38
|
-
return ueaBalance - gasReserve;
|
|
39
|
-
if (ueaBalance > BigInt(0))
|
|
40
|
-
return ueaBalance < requiredValue ? ueaBalance : requiredValue;
|
|
41
|
-
return BigInt(0);
|
|
42
|
-
}
|
|
43
29
|
/**
|
|
44
30
|
* Pre-flight check. PRC-20 balance is checked before the native check —
|
|
45
31
|
* a missing burn token fails before the gas-balance check, so the user
|
|
46
|
-
* sees the actionable PRC-20 shortfall instead of a stale
|
|
47
|
-
*
|
|
48
|
-
* Returns a result object instead of throwing for the legacy opt-out
|
|
49
|
-
* path. The throw happens here (not in the caller) for the default
|
|
50
|
-
* `allowUnderfundedSwap=false` case so all 6 paths share one throw site.
|
|
32
|
+
* sees the actionable PRC-20 shortfall instead of a stale native PC error.
|
|
51
33
|
*/
|
|
52
34
|
function runPreflight(opts) {
|
|
53
|
-
const { ctx, ueaAddress, ueaBalance, requiredValue, gasReserve, pathTag, burnToken, burnAmount, prc20Balance, segmentIndex,
|
|
35
|
+
const { ctx, ueaAddress, ueaBalance, requiredValue, gasReserve, pathTag, burnToken, burnAmount, prc20Balance, segmentIndex, } = opts;
|
|
54
36
|
// Each route bucket gets its own preflight IDs so hook streams stay
|
|
55
37
|
// self-consistent within their convention (R2 → 203-xx, R3 → 303-xx,
|
|
56
38
|
// cascade → 003-xx). The three hook formatters share an identical
|
|
@@ -75,15 +57,6 @@ function runPreflight(opts) {
|
|
|
75
57
|
(0, context_1.fireProgressHook)(ctx, HOOK_PRE_INFO, burnAmount, onHand, sufficient, ueaAddress, pathTag, { kind: 'PRC20', burnToken, segmentIndex });
|
|
76
58
|
if (!sufficient) {
|
|
77
59
|
const shortfall = burnAmount - onHand;
|
|
78
|
-
if (allowUnderfundedSwap) {
|
|
79
|
-
(0, context_1.printLog)(ctx, `[preflight ${pathTag}] PRC-20 shortfall ${shortfall} of ${burnToken}; ` +
|
|
80
|
-
`allowUnderfundedSwap=true — proceeding with legacy clamp behaviour, ` +
|
|
81
|
-
`swap is expected to revert with InsufficientBalance(0xf4d678b8) on-chain.`);
|
|
82
|
-
return {
|
|
83
|
-
ok: false,
|
|
84
|
-
legacyClampedValue: legacyClamp(ueaBalance, requiredValue, gasReserve),
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
60
|
(0, context_1.fireProgressHook)(ctx, HOOK_PRE_FAIL, burnAmount, onHand, shortfall, ueaAddress, pathTag, { kind: 'PRC20', burnToken, segmentIndex });
|
|
88
61
|
throw new errors_1.InsufficientUEABalanceError({
|
|
89
62
|
required: burnAmount,
|
|
@@ -105,13 +78,6 @@ function runPreflight(opts) {
|
|
|
105
78
|
return { ok: true, adjustedValue: requiredValue };
|
|
106
79
|
}
|
|
107
80
|
const shortfall = totalRequired - ueaBalance;
|
|
108
|
-
if (allowUnderfundedSwap) {
|
|
109
|
-
const clamped = legacyClamp(ueaBalance, requiredValue, gasReserve);
|
|
110
|
-
(0, context_1.printLog)(ctx, `[preflight ${pathTag}] UPC shortfall ${shortfall} wei; ` +
|
|
111
|
-
`allowUnderfundedSwap=true — proceeding with legacy clamped value ${clamped}, ` +
|
|
112
|
-
`swap may revert inside Uniswap with Error("STF") if the clamp under-funds the pool quote.`);
|
|
113
|
-
return { ok: false, legacyClampedValue: clamped };
|
|
114
|
-
}
|
|
115
81
|
(0, context_1.fireProgressHook)(ctx, HOOK_PRE_FAIL, totalRequired, ueaBalance, shortfall, ueaAddress, pathTag, { kind: 'NATIVE', segmentIndex });
|
|
116
82
|
throw new errors_1.InsufficientUEABalanceError({
|
|
117
83
|
required: totalRequired,
|
|
@@ -20,6 +20,7 @@ const context_1 = require("./context");
|
|
|
20
20
|
const error_decoder_1 = require("./error-decoder");
|
|
21
21
|
const errors_1 = require("./errors");
|
|
22
22
|
Object.defineProperty(exports, "PushChainExecutionError", { enumerable: true, get: function () { return errors_1.PushChainExecutionError; } });
|
|
23
|
+
const formatters_1 = require("../../formatters");
|
|
23
24
|
// ============================================================================
|
|
24
25
|
// sendPushTx
|
|
25
26
|
// ============================================================================
|
|
@@ -302,7 +303,10 @@ function extractPcTxAndTransform(ctx, pushChainUniversalTx, gatewayTxHash, event
|
|
|
302
303
|
const failedPcTx = (lastPcTransaction === null || lastPcTransaction === void 0 ? void 0 : lastPcTransaction.status) === 'FAILED'
|
|
303
304
|
? lastPcTransaction
|
|
304
305
|
: pushChainUniversalTx.pcTx.find((pcTx) => pcTx.status === 'FAILED' && pcTx.errorMsg);
|
|
305
|
-
const
|
|
306
|
+
const failedPcTxErrorMsg = (failedPcTx === null || failedPcTx === void 0 ? void 0 : failedPcTx.errorMsg)
|
|
307
|
+
? (0, formatters_1.normalizePcInsufficientFundsError)(failedPcTx.errorMsg)
|
|
308
|
+
: '';
|
|
309
|
+
const errorDetails = failedPcTxErrorMsg ? `: ${failedPcTxErrorMsg}` : '';
|
|
306
310
|
// Decode known revert selectors and ABI-encoded `Error(string)` reverts
|
|
307
311
|
// into actionable hints. Unknown selectors are logged at INFO so the
|
|
308
312
|
// table can grow from real reverts.
|
|
@@ -536,7 +536,7 @@ function transformToUniversalTxResponse(ctx_1, tx_1) {
|
|
|
536
536
|
accessList: Array.isArray(tx.accessList) ? [...tx.accessList] : [],
|
|
537
537
|
// 6. Utilities
|
|
538
538
|
wait: (waitOptions) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
539
|
-
var _a, _b, _c, _d, _e, _f;
|
|
539
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
540
540
|
// For trackTransaction replays the tx is historical — cosmos already
|
|
541
541
|
// has the full graph indexed, so the 20s/30s initial-wait buffers
|
|
542
542
|
// designed for live sends are pure deadweight. Default them to 0 when
|
|
@@ -605,9 +605,17 @@ function transformToUniversalTxResponse(ctx_1, tx_1) {
|
|
|
605
605
|
timeout: outboundTimeoutMs,
|
|
606
606
|
progressHook: outboundTranslator,
|
|
607
607
|
});
|
|
608
|
-
|
|
609
|
-
//
|
|
610
|
-
|
|
608
|
+
// `outboundDetails.externalTxHash` is the raw `0x`-hex form (kept
|
|
609
|
+
// internally so the R3 inbound tracker below can query Cosmos with
|
|
610
|
+
// it via `waitForInboundPushTx → findChildUtxIdFromExternalTx`).
|
|
611
|
+
// For every USER-FACING surface (progress hook event + receipt) we
|
|
612
|
+
// want the chain-native form so consumers can paste it straight
|
|
613
|
+
// into an explorer / RPC: base58 for SVM, hex for EVM. Build a
|
|
614
|
+
// display copy and use it for both the hook and the receipt.
|
|
615
|
+
const displayExternalTxHash = (_f = (0, helpers_1.toExternalTxHashDisplay)(outboundDetails.destinationChain, outboundDetails.externalTxHash)) !== null && _f !== void 0 ? _f : outboundDetails.externalTxHash;
|
|
616
|
+
const userFacingOutboundDetails = Object.assign(Object.assign({}, outboundDetails), { externalTxHash: displayExternalTxHash });
|
|
617
|
+
emit(hooks.success(userFacingOutboundDetails));
|
|
618
|
+
baseReceipt = Object.assign(Object.assign({}, baseReceipt), { externalTxHash: displayExternalTxHash, externalChain: outboundDetails.destinationChain, externalExplorerUrl: outboundDetails.explorerUrl, externalRecipient: outboundDetails.recipient, externalAmount: outboundDetails.amount, externalAssetAddr: outboundDetails.assetAddr, externalStatus: 'success' });
|
|
611
619
|
// R3 round-trip: poll Push Chain for the inbound tx that the
|
|
612
620
|
// source-chain CEA's sendUniversalTxToUEA call produces. Correlate
|
|
613
621
|
// via the outbound external tx hash → child UTX id → child pcTx.
|
|
@@ -637,7 +645,7 @@ function transformToUniversalTxResponse(ctx_1, tx_1) {
|
|
|
637
645
|
}
|
|
638
646
|
else {
|
|
639
647
|
// status === 'failed' (terminal failure status from chain)
|
|
640
|
-
const failMsg = (
|
|
648
|
+
const failMsg = (_g = inbound.errorMessage) !== null && _g !== void 0 ? _g : 'inbound execution failed on Push Chain';
|
|
641
649
|
emit(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_399_02](failMsg, 'inbound', targetChain));
|
|
642
650
|
baseReceipt = Object.assign(Object.assign({}, baseReceipt), { pushInboundUtxId: inbound.childUtxId, pushInboundTxHash: inbound.pushTxHash || undefined, externalStatus: 'failed', externalError: failMsg });
|
|
643
651
|
}
|
|
@@ -669,8 +677,16 @@ function transformToUniversalTxResponse(ctx_1, tx_1) {
|
|
|
669
677
|
// observed tx hash is carried by OutboundFailedError — expose it
|
|
670
678
|
// as externalTxHash so consumers can link to the explorer.
|
|
671
679
|
const failedExternalTxHash = error instanceof outbound_sync_1.OutboundFailedError ? error.externalTxHash : undefined;
|
|
672
|
-
|
|
673
|
-
|
|
680
|
+
// Normalize to chain-native display form for SVM (base58); EVM hex
|
|
681
|
+
// passes through unchanged. `OutboundFailedError.destinationChain`
|
|
682
|
+
// is a chain namespace string (e.g., 'solana:devnet') — convert to
|
|
683
|
+
// the CHAIN enum via the same helper used in outbound-sync.
|
|
684
|
+
const failedChain = error instanceof outbound_sync_1.OutboundFailedError && error.destinationChain
|
|
685
|
+
? (_h = (0, helpers_1.chainFromNamespace)(error.destinationChain)) !== null && _h !== void 0 ? _h : undefined
|
|
686
|
+
: undefined;
|
|
687
|
+
const failedExternalTxHashDisplay = (_j = (0, helpers_1.toExternalTxHashDisplay)(failedChain, failedExternalTxHash)) !== null && _j !== void 0 ? _j : failedExternalTxHash;
|
|
688
|
+
baseReceipt = Object.assign(Object.assign(Object.assign({}, baseReceipt), { externalStatus: isTimeout ? 'timeout' : 'failed', externalError: errMsg }), (failedExternalTxHashDisplay
|
|
689
|
+
? { externalTxHash: failedExternalTxHashDisplay }
|
|
674
690
|
: {}));
|
|
675
691
|
// Outbound polling timed out or failed — return the annotated
|
|
676
692
|
// receipt without throwing. Push Chain tx succeeded, external
|