@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 +1 -1
- package/src/lib/orchestrator/data-utils.d.ts +5 -0
- package/src/lib/orchestrator/data-utils.js +13 -0
- package/src/lib/orchestrator/internals/cascade.js +129 -91
- package/src/lib/orchestrator/internals/context.js +2 -3
- package/src/lib/orchestrator/internals/execute-funds-only.js +23 -3
- package/src/lib/orchestrator/internals/preflight.d.ts +3 -2
- package/src/lib/orchestrator/internals/preflight.js +3 -2
- package/src/lib/orchestrator/internals/progress-route-hooks.d.ts +0 -1
- package/src/lib/orchestrator/internals/progress-route-hooks.js +0 -2
- package/src/lib/orchestrator/internals/response-builder.js +1 -33
- package/src/lib/orchestrator/internals/route-handlers.js +62 -48
- package/src/lib/orchestrator/internals/tx-transformer.js +7 -11
- package/src/lib/orchestrator/orchestrator.js +5 -4
- package/src/lib/orchestrator/orchestrator.types.d.ts +12 -0
- package/src/lib/orchestrator/payload-builders.d.ts +2 -1
- package/src/lib/orchestrator/payload-builders.js +22 -14
- package/src/lib/orchestrator/route-detector.js +2 -1
- package/src/lib/progress-hook/progress-hook.js +26 -12
- package/src/lib/progress-hook/progress-hook.types.d.ts +7 -5
- package/src/lib/progress-hook/progress-hook.types.js +4 -3
- package/src/lib/push-chain/push-chain.d.ts +2 -0
|
@@ -29,30 +29,14 @@ const inbound_tracker_1 = require("./inbound-tracker");
|
|
|
29
29
|
const tx_transformer_1 = require("./tx-transformer");
|
|
30
30
|
const progress_route_hooks_1 = require("./progress-route-hooks");
|
|
31
31
|
const outbound_sync_1 = require("./outbound-sync");
|
|
32
|
-
/**
|
|
33
|
-
* Intermediate Push-success markers (199-99-99 for R3, 299-99 for R2) are
|
|
34
|
-
* internal transition signals — they tell response-builder's wait-phase
|
|
35
|
-
* branch that the Push leg has settled so it can skip re-emitting the
|
|
36
|
-
* intermediate marker on top of a reconstructed stream. They are not part
|
|
37
|
-
* of the published 1XX/2XX/3XX/4XX spec and are suppressed at the consumer
|
|
38
|
-
* dispatch boundary. `printLog` still fires for these so internal traces
|
|
39
|
-
* retain the transition record.
|
|
40
|
-
*/
|
|
41
|
-
const INTERMEDIATE_INTERNAL_IDS = new Set([
|
|
42
|
-
progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_99_99,
|
|
43
|
-
progress_hook_types_1.PROGRESS_HOOK.SEND_TX_299_99,
|
|
44
|
-
]);
|
|
45
32
|
/**
|
|
46
33
|
* Fan out a progress event to one or two registered callbacks, deduping
|
|
47
34
|
* when both slots hold the same reference. Keeps the emission policy in a
|
|
48
35
|
* single place shared by `emitProgress` (execute phase) and `emit` (wait
|
|
49
36
|
* phase) — so consumers that wire the same callback at multiple levels
|
|
50
|
-
* never see double-invocation.
|
|
51
|
-
* here so they never reach the consumer.
|
|
37
|
+
* never see double-invocation.
|
|
52
38
|
*/
|
|
53
39
|
function fanOut(event, primary, secondary) {
|
|
54
|
-
if (INTERMEDIATE_INTERNAL_IDS.has(event.id))
|
|
55
|
-
return;
|
|
56
40
|
if (primary)
|
|
57
41
|
primary(event);
|
|
58
42
|
if (secondary && secondary !== primary)
|
|
@@ -549,13 +533,6 @@ function transformToUniversalTxResponse(ctx_1, tx_1) {
|
|
|
549
533
|
const inboundInitialWaitMs = isReplay
|
|
550
534
|
? 0
|
|
551
535
|
: callbacks.inboundConstants.initialWaitMs;
|
|
552
|
-
// Track whether reconstruction already emitted the route's
|
|
553
|
-
// intermediate Push-success marker (299-99 / 199-99-99). When it has,
|
|
554
|
-
// skip re-emitting from the outbound branch below to avoid duplicates.
|
|
555
|
-
// This flag is only true when `this` response was created by
|
|
556
|
-
// trackTransaction() and the reconstructed stream already fired.
|
|
557
|
-
const alreadyReconstructed = universalTxResponse._eventsReconstructed === true;
|
|
558
|
-
let intermediateAlreadyEmitted = alreadyReconstructed;
|
|
559
536
|
// Build the base receipt directly from this response. Any per-call
|
|
560
537
|
// `tx.progressHook(cb)` already replayed buffered execute-phase events
|
|
561
538
|
// to `cb` via the progressHook setter — re-running trackTransaction
|
|
@@ -580,15 +557,6 @@ function transformToUniversalTxResponse(ctx_1, tx_1) {
|
|
|
580
557
|
return;
|
|
581
558
|
fanOut(event, registeredProgressHook, ctx.progressHook);
|
|
582
559
|
};
|
|
583
|
-
// Intermediate INFO marker — Push Chain tx confirmed, external/inbound
|
|
584
|
-
// leg still pending. Per spec, R1 keeps 199-01 as terminal; R2/R3
|
|
585
|
-
// reclassify Push success as intermediate. Skip when trackTransaction
|
|
586
|
-
// (called above) already reconstructed the same marker via
|
|
587
|
-
// reconstructR2/R3, otherwise the consumer sees 299-99 / 199-99-99
|
|
588
|
-
// twice in their stream.
|
|
589
|
-
if (hooks.intermediatePushOk && !intermediateAlreadyEmitted) {
|
|
590
|
-
emit(hooks.intermediatePushOk(targetChain, tx.hash));
|
|
591
|
-
}
|
|
592
560
|
// Awaiting relay
|
|
593
561
|
emit(hooks.awaiting(targetChain));
|
|
594
562
|
let lastEmittedStatus;
|
|
@@ -39,6 +39,7 @@ const price_fetch_1 = require("../../price-fetch/price-fetch");
|
|
|
39
39
|
const route_detector_1 = require("../route-detector");
|
|
40
40
|
const cea_utils_1 = require("../cea-utils");
|
|
41
41
|
const build_payload_1 = require("../svm-idl/build-payload");
|
|
42
|
+
const data_utils_1 = require("../data-utils");
|
|
42
43
|
const payload_builders_1 = require("../payload-builders");
|
|
43
44
|
const selectors_1 = require("../../constants/selectors");
|
|
44
45
|
const erc20_evm_1 = require("../../constants/abi/erc20.evm");
|
|
@@ -73,7 +74,7 @@ function resolveR2Prc20TokenEvm(params, targetChain, pushNetwork) {
|
|
|
73
74
|
prc20Token = (0, helpers_1.getNativePRC20ForChain)(targetChain, pushNetwork);
|
|
74
75
|
burnAmount = params.value;
|
|
75
76
|
}
|
|
76
|
-
else if (params.data) {
|
|
77
|
+
else if ((0, data_utils_1.hasExecutablePayloadData)(params.data)) {
|
|
77
78
|
// PAYLOAD-only (no value transfer): still need native token for chain namespace + gas fees
|
|
78
79
|
prc20Token = (0, helpers_1.getNativePRC20ForChain)(targetChain, pushNetwork);
|
|
79
80
|
burnAmount = BigInt(0);
|
|
@@ -132,12 +133,19 @@ function resolveR3SvmDrain(params, sourceChain, pushNetwork) {
|
|
|
132
133
|
return { prc20Token, drainAmount, tokenMintHex };
|
|
133
134
|
}
|
|
134
135
|
function buildR3SvmExtraPayload(ctx, params, ueaAddress, sourceChain, inboundNonce) {
|
|
135
|
-
|
|
136
|
+
var _a, _b;
|
|
137
|
+
const shouldBuildPushPayload = (0, data_utils_1.hasExecutablePayloadData)(params.data) ||
|
|
138
|
+
Boolean(((_a = params.funds) === null || _a === void 0 ? void 0 : _a.amount) && ((_b = params.value) !== null && _b !== void 0 ? _b : BigInt(0)) > BigInt(0));
|
|
139
|
+
if (!shouldBuildPushPayload) {
|
|
136
140
|
return undefined;
|
|
137
141
|
}
|
|
138
142
|
const executeParams = (0, helpers_1.toExecuteParams)(params);
|
|
139
143
|
const multicallCtx = Object.assign(Object.assign({}, ctx), { universalSigner: Object.assign(Object.assign({}, ctx.universalSigner), { account: Object.assign(Object.assign({}, ctx.universalSigner.account), { chain: sourceChain }) }) });
|
|
140
|
-
const multicallPayload = (0, payload_builder_1.buildMulticallPayloadData)(multicallCtx, executeParams.to, (0, payload_builders_1.buildExecuteMulticall)({
|
|
144
|
+
const multicallPayload = (0, payload_builder_1.buildMulticallPayloadData)(multicallCtx, executeParams.to, (0, payload_builders_1.buildExecuteMulticall)({
|
|
145
|
+
execute: executeParams,
|
|
146
|
+
ueaAddress,
|
|
147
|
+
allowSelfValueCall: true,
|
|
148
|
+
}));
|
|
141
149
|
const inboundPayload = (0, payload_builders_1.buildInboundUniversalPayload)(multicallPayload, {
|
|
142
150
|
nonce: inboundNonce !== null && inboundNonce !== void 0 ? inboundNonce : BigInt(0),
|
|
143
151
|
});
|
|
@@ -149,12 +157,13 @@ function buildR3SvmExtraPayload(ctx, params, ueaAddress, sourceChain, inboundNon
|
|
|
149
157
|
* multicall when the target IS the CEA (avoids a CEA._handleMulticall revert).
|
|
150
158
|
*/
|
|
151
159
|
function buildR2CeaPayloadEvm(params, ceaAddress, targetAddress) {
|
|
152
|
-
var _a, _b, _c;
|
|
160
|
+
var _a, _b, _c, _d, _e;
|
|
153
161
|
if (params.migration) {
|
|
154
162
|
return (0, payload_builders_1.buildMigrationPayload)();
|
|
155
163
|
}
|
|
156
164
|
const ceaMulticalls = [];
|
|
157
|
-
|
|
165
|
+
const hasData = (0, data_utils_1.hasExecutablePayloadData)(params.data);
|
|
166
|
+
if (hasData) {
|
|
158
167
|
if (Array.isArray(params.data)) {
|
|
159
168
|
ceaMulticalls.push(...params.data);
|
|
160
169
|
}
|
|
@@ -186,36 +195,13 @@ function buildR2CeaPayloadEvm(params, ceaAddress, targetAddress) {
|
|
|
186
195
|
});
|
|
187
196
|
}
|
|
188
197
|
}
|
|
189
|
-
else
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
data: '0x',
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
else if ((_c = params.funds) === null || _c === void 0 ? void 0 : _c.amount) {
|
|
201
|
-
// Funds-only transfer (no data, no value). Without this branch the CEA
|
|
202
|
-
// multicall is empty and the relayed funds sit in the CEA instead of
|
|
203
|
-
// being forwarded to the caller's recipient.
|
|
204
|
-
const token = params.funds.token;
|
|
205
|
-
if (token) {
|
|
206
|
-
if (token.mechanism === 'native') {
|
|
207
|
-
// Native funds (e.g. pETH → ETH): forward value to the recipient.
|
|
208
|
-
// Self-CEA is skipped — the gateway already deposits into the CEA.
|
|
209
|
-
if (targetAddress.toLowerCase() !== ceaAddress.toLowerCase()) {
|
|
210
|
-
ceaMulticalls.push({
|
|
211
|
-
to: targetAddress,
|
|
212
|
-
value: params.funds.amount,
|
|
213
|
-
data: '0x',
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
// ERC-20 funds: forward via ERC20.transfer from the CEA.
|
|
198
|
+
else {
|
|
199
|
+
const token = ((_c = params.funds) === null || _c === void 0 ? void 0 : _c.amount)
|
|
200
|
+
? params.funds.token
|
|
201
|
+
: undefined;
|
|
202
|
+
if (((_d = params.funds) === null || _d === void 0 ? void 0 : _d.amount) && token && token.mechanism !== 'native') {
|
|
203
|
+
// ERC-20 funds: forward via ERC20.transfer from the CEA.
|
|
204
|
+
if (token) {
|
|
219
205
|
const erc20Transfer = (0, viem_1.encodeFunctionData)({
|
|
220
206
|
abi: erc20_evm_1.ERC20_EVM,
|
|
221
207
|
functionName: 'transfer',
|
|
@@ -228,6 +214,28 @@ function buildR2CeaPayloadEvm(params, ceaAddress, targetAddress) {
|
|
|
228
214
|
});
|
|
229
215
|
}
|
|
230
216
|
}
|
|
217
|
+
if (params.value) {
|
|
218
|
+
// Native value transfer only. Skip the multicall when sending to the CEA
|
|
219
|
+
// itself — a value-bearing self-call would revert in CEA._handleMulticall.
|
|
220
|
+
if (targetAddress.toLowerCase() !== ceaAddress.toLowerCase()) {
|
|
221
|
+
ceaMulticalls.push({
|
|
222
|
+
to: targetAddress,
|
|
223
|
+
value: params.value,
|
|
224
|
+
data: '0x',
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else if (((_e = params.funds) === null || _e === void 0 ? void 0 : _e.amount) && (token === null || token === void 0 ? void 0 : token.mechanism) === 'native') {
|
|
229
|
+
// Native funds (e.g. pETH → ETH): forward value to the recipient.
|
|
230
|
+
// Self-CEA is skipped — the gateway already deposits into the CEA.
|
|
231
|
+
if (targetAddress.toLowerCase() !== ceaAddress.toLowerCase()) {
|
|
232
|
+
ceaMulticalls.push({
|
|
233
|
+
to: targetAddress,
|
|
234
|
+
value: params.funds.amount,
|
|
235
|
+
data: '0x',
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
231
239
|
}
|
|
232
240
|
return (0, payload_builders_1.buildCeaMulticallPayload)(ceaMulticalls);
|
|
233
241
|
}
|
|
@@ -361,7 +369,9 @@ function executeUoaToCea(ctx, params, executeFn) {
|
|
|
361
369
|
if (params.value && params.value > BigInt(0)) {
|
|
362
370
|
(0, context_1.printLog)(ctx, `executeUoaToCea — auto-selected native PRC-20 ${prc20Token} for chain ${targetChain}, amount: ${burnAmount.toString()}`);
|
|
363
371
|
}
|
|
364
|
-
else if (!params.migration &&
|
|
372
|
+
else if (!params.migration &&
|
|
373
|
+
!((_a = params.funds) === null || _a === void 0 ? void 0 : _a.amount) &&
|
|
374
|
+
(0, data_utils_1.hasExecutablePayloadData)(params.data)) {
|
|
365
375
|
(0, context_1.printLog)(ctx, `executeUoaToCea — PAYLOAD-only: using native PRC-20 ${prc20Token} for chain ${targetChain} with zero burn amount`);
|
|
366
376
|
}
|
|
367
377
|
const gasLimitForQuery = (_b = params.gasLimit) !== null && _b !== void 0 ? _b : BigInt(0);
|
|
@@ -804,7 +814,7 @@ function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
|
804
814
|
*/
|
|
805
815
|
function executeCeaToPush(ctx, params, executeFn) {
|
|
806
816
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
807
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
817
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
808
818
|
// 1. Validate and extract source chain
|
|
809
819
|
if (!((_a = params.from) === null || _a === void 0 ? void 0 : _a.chain)) {
|
|
810
820
|
throw new Error('Route 3 (CEA -> Push) requires from.chain to specify the source CEA chain');
|
|
@@ -893,7 +903,8 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
893
903
|
// The relay expects a full UniversalPayload struct (to, value, data, gasLimit, ...),
|
|
894
904
|
// where `data` contains the multicall payload (with UEA_MULTICALL_SELECTOR prefix).
|
|
895
905
|
let pushPayload = '0x';
|
|
896
|
-
if (params.data)
|
|
906
|
+
if ((0, data_utils_1.hasExecutablePayloadData)(params.data) ||
|
|
907
|
+
(((_f = params.funds) === null || _f === void 0 ? void 0 : _f.amount) && ((_g = params.value) !== null && _g !== void 0 ? _g : BigInt(0)) > BigInt(0))) {
|
|
897
908
|
const multicallData = (0, payload_builders_1.buildExecuteMulticall)({
|
|
898
909
|
execute: {
|
|
899
910
|
to: pushDestination,
|
|
@@ -901,6 +912,7 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
901
912
|
data: params.data,
|
|
902
913
|
},
|
|
903
914
|
ueaAddress,
|
|
915
|
+
allowSelfValueCall: true,
|
|
904
916
|
});
|
|
905
917
|
const multicallPayload = (0, payload_builder_1.buildMulticallPayloadData)(ctx, pushDestination, multicallData);
|
|
906
918
|
// Use ueaNonce + 1: the outbound tx itself consumes one nonce via execute(),
|
|
@@ -933,7 +945,7 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
933
945
|
// tokens FROM the CEA back to Push Chain, not to round-trip them.
|
|
934
946
|
const prc20Token = (0, helpers_1.getNativePRC20ForChain)(sourceChain, ctx.pushNetwork);
|
|
935
947
|
const burnAmount = BigInt(0);
|
|
936
|
-
const outboundGasLimit = (
|
|
948
|
+
const outboundGasLimit = (_h = params.gasLimit) !== null && _h !== void 0 ? _h : selectors_1.DEFAULT_CEA_TO_PUSH_GAS_LIMIT;
|
|
937
949
|
(0, context_1.printLog)(ctx, `executeCeaToPush — prc20Token: ${prc20Token}, burnAmount: ${burnAmount.toString()}`);
|
|
938
950
|
// 9. Build outbound request (same structure as Route 2)
|
|
939
951
|
// recipient = CEA address (for self-execution), value = 0 in payload
|
|
@@ -942,7 +954,7 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
942
954
|
burnAmount, // amount: 0 (payload-only, CEA uses its own balance)
|
|
943
955
|
outboundGasLimit, ceaPayload, // payload: ABI-encoded CEA multicall
|
|
944
956
|
ueaAddress, // revertRecipient: UEA
|
|
945
|
-
(
|
|
957
|
+
(_j = params.maxPCForGas) !== null && _j !== void 0 ? _j : BigInt(0));
|
|
946
958
|
(0, context_1.printLog)(ctx, `executeCeaToPush — outbound request: ${JSON.stringify({
|
|
947
959
|
recipient: outboundReq.recipient,
|
|
948
960
|
token: outboundReq.token,
|
|
@@ -973,8 +985,8 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
973
985
|
protocolFeeR3 = result.protocolFee;
|
|
974
986
|
nativeValueForGas = result.nativeValueForGas;
|
|
975
987
|
sizingDecisionR3 = result.sizing;
|
|
976
|
-
outboundReq = (0, payload_builders_1.buildOutboundRequest)(ceaAddress, prc20Token, burnAmount, outboundGasLimit, ceaPayload, ueaAddress, (
|
|
977
|
-
(0, context_1.printLog)(ctx, `executeCeaToPush — queried gas fee: ${gasFee.toString()}, gasToken: ${gasToken}, nativeValueForGas: ${nativeValueForGas.toString()}, sizing=${(
|
|
988
|
+
outboundReq = (0, payload_builders_1.buildOutboundRequest)(ceaAddress, prc20Token, burnAmount, outboundGasLimit, ceaPayload, ueaAddress, (_k = params.maxPCForGas) !== null && _k !== void 0 ? _k : BigInt(0), outboundGasPriceR3);
|
|
989
|
+
(0, context_1.printLog)(ctx, `executeCeaToPush — queried gas fee: ${gasFee.toString()}, gasToken: ${gasToken}, nativeValueForGas: ${nativeValueForGas.toString()}, sizing=${(_m = (_l = result.sizing) === null || _l === void 0 ? void 0 : _l.category) !== null && _m !== void 0 ? _m : 'legacy'}`);
|
|
978
990
|
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_302_02, sourceChain, protocolFeeR3, gasFee);
|
|
979
991
|
}
|
|
980
992
|
catch (err) {
|
|
@@ -1056,7 +1068,7 @@ function executeCeaToPush(ctx, params, executeFn) {
|
|
|
1056
1068
|
requiredValue: nativeValueForGas,
|
|
1057
1069
|
gasReserve: OUTBOUND_GAS_RESERVE_R3,
|
|
1058
1070
|
pathTag: 'R3_EVM',
|
|
1059
|
-
enforceGasCheck: ((
|
|
1071
|
+
enforceGasCheck: ((_o = params.options) === null || _o === void 0 ? void 0 : _o.enforceGasCheck) === true,
|
|
1060
1072
|
});
|
|
1061
1073
|
// 12. Build Push Chain multicalls (approvals + sendUniversalTxOutbound)
|
|
1062
1074
|
const pushChainMulticalls = (0, payload_builders_1.buildOutboundApprovalAndCall)({
|
|
@@ -1343,7 +1355,7 @@ function executeCeaToCea(ctx, params, executeFn) {
|
|
|
1343
1355
|
*/
|
|
1344
1356
|
function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
1345
1357
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
1346
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
1358
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
1347
1359
|
const ueaAddress = (0, uea_manager_1.computeUEAOffchain)(ctx);
|
|
1348
1360
|
switch (route) {
|
|
1349
1361
|
case route_detector_1.TransactionRoute.UOA_TO_PUSH: {
|
|
@@ -1396,7 +1408,7 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1396
1408
|
const { cea: ceaAddress } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, target.chain, (_d = ctx.rpcUrls[target.chain]) === null || _d === void 0 ? void 0 : _d[0]);
|
|
1397
1409
|
// Build CEA outbound payload
|
|
1398
1410
|
const multicalls = [];
|
|
1399
|
-
if (params.data) {
|
|
1411
|
+
if ((0, data_utils_1.hasExecutablePayloadData)(params.data)) {
|
|
1400
1412
|
if (Array.isArray(params.data)) {
|
|
1401
1413
|
multicalls.push(...params.data);
|
|
1402
1414
|
}
|
|
@@ -1503,7 +1515,8 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1503
1515
|
// Build Push Chain payload (what executes after inbound arrives)
|
|
1504
1516
|
// Wrap in UniversalPayload struct for the relay.
|
|
1505
1517
|
let pushPayload = '0x';
|
|
1506
|
-
if (params.data)
|
|
1518
|
+
if ((0, data_utils_1.hasExecutablePayloadData)(params.data) ||
|
|
1519
|
+
(((_o = params.funds) === null || _o === void 0 ? void 0 : _o.amount) && ((_p = params.value) !== null && _p !== void 0 ? _p : BigInt(0)) > BigInt(0))) {
|
|
1507
1520
|
const multicallData = (0, payload_builders_1.buildExecuteMulticall)({
|
|
1508
1521
|
execute: {
|
|
1509
1522
|
to: pushDestination,
|
|
@@ -1511,6 +1524,7 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1511
1524
|
data: params.data,
|
|
1512
1525
|
},
|
|
1513
1526
|
ueaAddress,
|
|
1527
|
+
allowSelfValueCall: true,
|
|
1514
1528
|
});
|
|
1515
1529
|
const multicallPayload = (0, payload_builder_1.buildMulticallPayloadData)(ctx, pushDestination, multicallData);
|
|
1516
1530
|
pushPayload = (0, payload_builders_1.buildInboundUniversalPayload)(multicallPayload, { nonce: ueaNonceHop + BigInt(1) });
|
|
@@ -1524,8 +1538,8 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1524
1538
|
// Route 3: CEA uses its own pre-existing balance — no PRC-20 burn needed.
|
|
1525
1539
|
// burnAmount = 0 makes this a payload-only outbound relay.
|
|
1526
1540
|
const burnAmount = BigInt(0);
|
|
1527
|
-
const outboundGasLimit = (
|
|
1528
|
-
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(ceaAddress, prc20Token, burnAmount, outboundGasLimit, ceaPayload, ueaAddress, (
|
|
1541
|
+
const outboundGasLimit = (_q = params.gasLimit) !== null && _q !== void 0 ? _q : selectors_1.DEFAULT_CEA_TO_PUSH_GAS_LIMIT;
|
|
1542
|
+
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(ceaAddress, prc20Token, burnAmount, outboundGasLimit, ceaPayload, ueaAddress, (_r = params.maxPCForGas) !== null && _r !== void 0 ? _r : BigInt(0));
|
|
1529
1543
|
return { payload: ceaPayload, gatewayRequest: outboundReq };
|
|
1530
1544
|
}
|
|
1531
1545
|
default:
|
|
@@ -160,11 +160,6 @@ function reconstructR2(universalTxResponse, universalTxData, isFailed, errorMsg)
|
|
|
160
160
|
if (isFailed) {
|
|
161
161
|
events.push(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_299_02](errorMsg));
|
|
162
162
|
}
|
|
163
|
-
else {
|
|
164
|
-
// Push Chain success is intermediate for R2 — the wait() outbound poll
|
|
165
|
-
// appends the real terminal (299-01/02/03) once the external leg resolves.
|
|
166
|
-
events.push(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_299_99](targetChain, universalTxResponse.hash));
|
|
167
|
-
}
|
|
168
163
|
return events;
|
|
169
164
|
}
|
|
170
165
|
function reconstructR3(universalTxResponse, universalTxData, isFailed, errorMsg) {
|
|
@@ -190,11 +185,6 @@ function reconstructR3(universalTxResponse, universalTxData, isFailed, errorMsg)
|
|
|
190
185
|
// "Push Chain Tx Failed" rather than the inbound copy.
|
|
191
186
|
events.push(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_399_02](errorMsg, 'push'));
|
|
192
187
|
}
|
|
193
|
-
else {
|
|
194
|
-
// Push Chain success is intermediate for R3 — wait() drives the source-chain
|
|
195
|
-
// CEA poll (309-xx) and the inbound-to-Push poll (310-xx / 399-xx) on top.
|
|
196
|
-
events.push(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_99_99](universalTxResponse.hash));
|
|
197
|
-
}
|
|
198
188
|
return events;
|
|
199
189
|
}
|
|
200
190
|
// ============================================================================
|
|
@@ -315,7 +305,7 @@ function reconstructMultichain(universalTxResponse, universalTxData, isFailed, e
|
|
|
315
305
|
let failedAt = null;
|
|
316
306
|
let failureMsg = errorMsg;
|
|
317
307
|
outbounds.forEach((ob, i) => {
|
|
318
|
-
var _a;
|
|
308
|
+
var _a, _b;
|
|
319
309
|
const hopNum = i + 1;
|
|
320
310
|
const fromChain = i === 0 ? sourceChain : outbounds[i - 1].destinationChain;
|
|
321
311
|
const toChain = ob.destinationChain;
|
|
@@ -336,6 +326,12 @@ function reconstructMultichain(universalTxResponse, universalTxData, isFailed, e
|
|
|
336
326
|
events.push(...reconstructR2(legResponse, legData, legFailed, legError));
|
|
337
327
|
}
|
|
338
328
|
if (!legFailed) {
|
|
329
|
+
if (hopNum < hopCount) {
|
|
330
|
+
const txHash = ((_b = ob.observedTx) === null || _b === void 0 ? void 0 : _b.txHash) || legResponse.hash;
|
|
331
|
+
events.push(isR3Leg
|
|
332
|
+
? progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_399_99](toChain, txHash)
|
|
333
|
+
: progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_299_99](toChain, txHash));
|
|
334
|
+
}
|
|
339
335
|
events.push(progress_hook_1.default[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_002_99_99](hopNum, hopCount));
|
|
340
336
|
}
|
|
341
337
|
else if (failedAt === null) {
|
|
@@ -7,6 +7,7 @@ const enums_1 = require("../constants/enums");
|
|
|
7
7
|
const progress_hook_types_1 = require("../progress-hook/progress-hook.types");
|
|
8
8
|
const push_client_1 = require("../push-client/push-client");
|
|
9
9
|
const route_detector_1 = require("./route-detector");
|
|
10
|
+
const data_utils_1 = require("./data-utils");
|
|
10
11
|
const internals_1 = require("./internals");
|
|
11
12
|
class Orchestrator {
|
|
12
13
|
/* @internal */ get pushClient() {
|
|
@@ -132,8 +133,9 @@ class Orchestrator {
|
|
|
132
133
|
execute(params, options) {
|
|
133
134
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
134
135
|
var _a, _b, _c, _d, _e;
|
|
135
|
-
|
|
136
|
-
|
|
136
|
+
const inlineProgressHook = params.progressHook;
|
|
137
|
+
if (options || inlineProgressHook) {
|
|
138
|
+
params = Object.assign(Object.assign({}, params), { options: Object.assign(Object.assign(Object.assign({}, params.options), (inlineProgressHook ? { progressHook: inlineProgressHook } : {})), options) });
|
|
137
139
|
}
|
|
138
140
|
const perCallHook = (_a = params.options) === null || _a === void 0 ? void 0 : _a.progressHook;
|
|
139
141
|
const originalExecuteHook = this.progressHook;
|
|
@@ -241,8 +243,7 @@ class Orchestrator {
|
|
|
241
243
|
}
|
|
242
244
|
// Standard Push Chain execution (Route 1)
|
|
243
245
|
const execute = params;
|
|
244
|
-
const
|
|
245
|
-
const hasData = execute.data && execute.data !== '0x';
|
|
246
|
+
const hasData = (0, data_utils_1.hasExecutablePayloadData)(execute.data);
|
|
246
247
|
const eventBuffer = [];
|
|
247
248
|
const originalHook = this.progressHook;
|
|
248
249
|
this.progressHook = (event) => {
|
|
@@ -101,6 +101,12 @@ export type ExecuteParams = {
|
|
|
101
101
|
* Optional transaction behavior switches.
|
|
102
102
|
*/
|
|
103
103
|
options?: TransactionExecutionOptions;
|
|
104
|
+
/**
|
|
105
|
+
* Optional per-call progress callback.
|
|
106
|
+
* Alias for `sendTransaction(params, { progressHook })`, kept so docs/UI
|
|
107
|
+
* examples can pass the hook inside the transaction object.
|
|
108
|
+
*/
|
|
109
|
+
progressHook?: TransactionExecutionOptions['progressHook'];
|
|
104
110
|
/**
|
|
105
111
|
* Optional: pay gas in a specific token. If not provided, use `token` (bridge token) when present; otherwise, native token.
|
|
106
112
|
*/
|
|
@@ -633,6 +639,8 @@ export interface CascadedTxResponse {
|
|
|
633
639
|
hops: CascadeHopInfo[];
|
|
634
640
|
/** Total number of hops in the cascade */
|
|
635
641
|
hopCount: number;
|
|
642
|
+
/** Final tx hash resolved by waitForAll()/wait(), when available */
|
|
643
|
+
finalTxHash?: string;
|
|
636
644
|
/** Wait for ALL hops to complete across all chains */
|
|
637
645
|
waitForAll: (opts?: CascadeTrackOptions) => Promise<CascadeCompletionResult>;
|
|
638
646
|
/** Convenience alias for waitForAll() */
|
|
@@ -707,6 +715,10 @@ export interface CascadeCompletionResult {
|
|
|
707
715
|
success: boolean;
|
|
708
716
|
/** Final state of all hops */
|
|
709
717
|
hops: CascadeHopInfo[];
|
|
718
|
+
/** Final tx hash for the last confirmed hop, when available */
|
|
719
|
+
finalTxHash?: string;
|
|
720
|
+
/** Original cascaded response object for consumers that need the full context */
|
|
721
|
+
finalTxResponse?: CascadedTxResponse;
|
|
710
722
|
/** Index of first failed hop (if any) */
|
|
711
723
|
failedAt?: number;
|
|
712
724
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { CHAIN } from '../constants/enums';
|
|
2
2
|
import type { ExecuteParams, MultiCall, UniversalOutboundTxRequest, SvmExecutePayloadFields } from './orchestrator.types';
|
|
3
|
-
export declare function buildExecuteMulticall({ execute, ueaAddress, logger, }: {
|
|
3
|
+
export declare function buildExecuteMulticall({ execute, ueaAddress, logger, allowSelfValueCall, }: {
|
|
4
4
|
execute: ExecuteParams;
|
|
5
5
|
ueaAddress: `0x${string}`;
|
|
6
6
|
logger?: (msg: string) => void;
|
|
7
|
+
allowSelfValueCall?: boolean;
|
|
7
8
|
}): MultiCall[];
|
|
8
9
|
/**
|
|
9
10
|
* Multicall tuple type definition for ABI encoding
|
|
@@ -23,14 +23,16 @@ const universalGatewayPC_evm_1 = require("../constants/abi/universalGatewayPC.ev
|
|
|
23
23
|
const selectors_1 = require("../constants/selectors");
|
|
24
24
|
const chain_1 = require("../constants/chain");
|
|
25
25
|
const enums_1 = require("../constants/enums");
|
|
26
|
-
|
|
26
|
+
const data_utils_1 = require("./data-utils");
|
|
27
|
+
function buildExecuteMulticall({ execute, ueaAddress, logger, allowSelfValueCall = false, }) {
|
|
27
28
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
28
29
|
const log = (msg) => logger === null || logger === void 0 ? void 0 : logger(msg);
|
|
30
|
+
const hasData = (0, data_utils_1.hasExecutablePayloadData)(execute.data);
|
|
29
31
|
log('buildExecuteMulticall — input: ' + JSON.stringify({
|
|
30
32
|
to: execute.to,
|
|
31
33
|
value: (_b = (_a = execute.value) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : 'undefined',
|
|
32
34
|
data: execute.data ? (Array.isArray(execute.data) ? `Array(${execute.data.length})` : execute.data.slice(0, 20) + '...') : 'undefined',
|
|
33
|
-
hasData
|
|
35
|
+
hasData,
|
|
34
36
|
fundsAmount: (_e = (_d = (_c = execute.funds) === null || _c === void 0 ? void 0 : _c.amount) === null || _d === void 0 ? void 0 : _d.toString()) !== null && _e !== void 0 ? _e : 'undefined',
|
|
35
37
|
fundsTokenSymbol: (_h = (_g = (_f = execute.funds) === null || _f === void 0 ? void 0 : _f.token) === null || _g === void 0 ? void 0 : _g.symbol) !== null && _h !== void 0 ? _h : 'undefined',
|
|
36
38
|
fundsTokenMechanism: (_l = (_k = (_j = execute.funds) === null || _j === void 0 ? void 0 : _j.token) === null || _k === void 0 ? void 0 : _k.mechanism) !== null && _l !== void 0 ? _l : 'undefined',
|
|
@@ -38,19 +40,25 @@ function buildExecuteMulticall({ execute, ueaAddress, logger, }) {
|
|
|
38
40
|
}, null, 2));
|
|
39
41
|
const multicallData = [];
|
|
40
42
|
// *** We will pass the value alongside with the data in a single message now ***
|
|
41
|
-
const branch1 = !
|
|
42
|
-
log(`buildExecuteMulticall — Branch 1 (!data && value): ${branch1} | !
|
|
43
|
-
if (!
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
const branch1 = !hasData && execute.value;
|
|
44
|
+
log(`buildExecuteMulticall — Branch 1 (!data && value): ${branch1} | !hasData: ${!hasData} | execute.value: ${(_o = (_m = execute.value) === null || _m === void 0 ? void 0 : _m.toString()) !== null && _o !== void 0 ? _o : 'undefined'}`);
|
|
45
|
+
if (!hasData && execute.value) {
|
|
46
|
+
const isValueToSelf = execute.to.toLowerCase() === ueaAddress.toLowerCase();
|
|
47
|
+
if (isValueToSelf && !allowSelfValueCall) {
|
|
48
|
+
log('buildExecuteMulticall — Branch 1 SKIPPED: native value targets the UEA itself; parking value via gateway deposit');
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
multicallData.push({
|
|
52
|
+
to: execute.to,
|
|
53
|
+
value: execute.value,
|
|
54
|
+
data: '0x',
|
|
55
|
+
});
|
|
56
|
+
log(`buildExecuteMulticall — Branch 1 ENTERED: pushed native value transfer to ${execute.to}`);
|
|
57
|
+
}
|
|
50
58
|
}
|
|
51
59
|
if ((_p = execute.funds) === null || _p === void 0 ? void 0 : _p.amount) {
|
|
52
60
|
const token = execute.funds.token;
|
|
53
|
-
const isArrayMulticall = Array.isArray(execute.data);
|
|
61
|
+
const isArrayMulticall = Array.isArray(execute.data) && execute.data.length > 0;
|
|
54
62
|
const isNative = token.mechanism === 'native';
|
|
55
63
|
log('buildExecuteMulticall — Branch 2 (funds): ' + JSON.stringify({
|
|
56
64
|
amount: execute.funds.amount.toString(),
|
|
@@ -82,8 +90,8 @@ function buildExecuteMulticall({ execute, ueaAddress, logger, }) {
|
|
|
82
90
|
else {
|
|
83
91
|
log('buildExecuteMulticall — Branch 2 SKIPPED: no funds.amount');
|
|
84
92
|
}
|
|
85
|
-
log(`buildExecuteMulticall — Branch 3 (execute.data): ${
|
|
86
|
-
if (
|
|
93
|
+
log(`buildExecuteMulticall — Branch 3 (execute.data): ${hasData}`);
|
|
94
|
+
if (hasData) {
|
|
87
95
|
// *************************
|
|
88
96
|
// Check for `execute.to`
|
|
89
97
|
// *************************
|
|
@@ -21,6 +21,7 @@ exports.getRouteInfo = getRouteInfo;
|
|
|
21
21
|
const enums_1 = require("../constants/enums");
|
|
22
22
|
const tokens_1 = require("../constants/tokens");
|
|
23
23
|
const payload_builders_1 = require("./payload-builders");
|
|
24
|
+
const data_utils_1 = require("./data-utils");
|
|
24
25
|
const normalize_address_1 = require("./svm-idl/normalize-address");
|
|
25
26
|
// ============================================================================
|
|
26
27
|
// Transaction Route Enum
|
|
@@ -247,7 +248,7 @@ function validateRouteParams(params, context) {
|
|
|
247
248
|
if (params.funds) {
|
|
248
249
|
throw new RouteValidationError('migration is incompatible with funds');
|
|
249
250
|
}
|
|
250
|
-
if (params.data) {
|
|
251
|
+
if ((0, data_utils_1.hasExecutablePayloadData)(params.data)) {
|
|
251
252
|
throw new RouteValidationError('migration is incompatible with data');
|
|
252
253
|
}
|
|
253
254
|
if (isChainTarget(params.to) && (0, payload_builders_1.isSvmChain)(params.to.chain)) {
|
|
@@ -23,10 +23,10 @@ const friendlyChain = (chainOrNs) => {
|
|
|
23
23
|
const key = utils_1.Utils.chains.getChainName(asString);
|
|
24
24
|
return key ? toTitleCase(key) : asString;
|
|
25
25
|
};
|
|
26
|
-
function preflightLevel(sufficient
|
|
26
|
+
function preflightLevel(sufficient) {
|
|
27
27
|
if (sufficient)
|
|
28
28
|
return 'INFO';
|
|
29
|
-
return
|
|
29
|
+
return 'WARNING';
|
|
30
30
|
}
|
|
31
31
|
function preflightSuffix(sufficient, pathTag, enforceGasCheck) {
|
|
32
32
|
if (sufficient)
|
|
@@ -273,6 +273,20 @@ const RAW_HOOKS_R1 = {
|
|
|
273
273
|
level: 'ERROR',
|
|
274
274
|
};
|
|
275
275
|
},
|
|
276
|
+
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_03]: (targetChain, elapsedMs) => ({
|
|
277
|
+
id: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_03,
|
|
278
|
+
title: `Syncing State with ${friendlyChain(targetChain)} Timeout`,
|
|
279
|
+
message: `Timed out waiting for UGPC relay to ${targetChain}`,
|
|
280
|
+
response: { error: 'relay timeout', chain: targetChain, elapsedMs },
|
|
281
|
+
level: 'ERROR',
|
|
282
|
+
}),
|
|
283
|
+
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_99]: (txHash) => ({
|
|
284
|
+
id: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_99,
|
|
285
|
+
title: 'Push Chain Tx Completed',
|
|
286
|
+
message: `Intermediate Push Chain tx confirmed: ${txHash}, progressing to next phase`,
|
|
287
|
+
response: { txHash },
|
|
288
|
+
level: 'INFO',
|
|
289
|
+
}),
|
|
276
290
|
};
|
|
277
291
|
// =============================================================================
|
|
278
292
|
// Route 2 — UEA → UGPC → CEA on target chain (201–299, signature-only)
|
|
@@ -342,7 +356,7 @@ const RAW_HOOKS_R2 = {
|
|
|
342
356
|
warningOnly: !sufficient && enforceGasCheck === false,
|
|
343
357
|
shortfall: (_d = extra === null || extra === void 0 ? void 0 : extra.shortfall) !== null && _d !== void 0 ? _d : null,
|
|
344
358
|
},
|
|
345
|
-
level: preflightLevel(sufficient
|
|
359
|
+
level: preflightLevel(sufficient),
|
|
346
360
|
};
|
|
347
361
|
},
|
|
348
362
|
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_203_04]: (required, available, shortfall, ueaAddress, pathTag, extra) => {
|
|
@@ -467,13 +481,6 @@ const RAW_HOOKS_R2 = {
|
|
|
467
481
|
// Route 3 — UEA → UGPC → CEA → sendUniversalTxToUEA → Push Chain (301–399)
|
|
468
482
|
// =============================================================================
|
|
469
483
|
const RAW_HOOKS_R3 = {
|
|
470
|
-
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_99_99]: (txHash) => ({
|
|
471
|
-
id: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_99_99,
|
|
472
|
-
title: 'Push Chain Tx Completed',
|
|
473
|
-
message: `Intermediate Push Chain tx confirmed: ${txHash}, progressing to next phase`,
|
|
474
|
-
response: { txHash },
|
|
475
|
-
level: 'INFO',
|
|
476
|
-
}),
|
|
477
484
|
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_301]: (sourceChain, ceaAddress) => ({
|
|
478
485
|
id: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_301,
|
|
479
486
|
title: `${friendlyChain(sourceChain)}'s Executor Account Detected`,
|
|
@@ -560,7 +567,7 @@ const RAW_HOOKS_R3 = {
|
|
|
560
567
|
warningOnly: !sufficient && enforceGasCheck === false,
|
|
561
568
|
shortfall: (_d = extra === null || extra === void 0 ? void 0 : extra.shortfall) !== null && _d !== void 0 ? _d : null,
|
|
562
569
|
},
|
|
563
|
-
level: preflightLevel(sufficient
|
|
570
|
+
level: preflightLevel(sufficient),
|
|
564
571
|
};
|
|
565
572
|
},
|
|
566
573
|
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_303_05]: (required, available, shortfall, ueaAddress, pathTag, extra) => {
|
|
@@ -727,6 +734,13 @@ const RAW_HOOKS_R3 = {
|
|
|
727
734
|
},
|
|
728
735
|
level: 'ERROR',
|
|
729
736
|
}),
|
|
737
|
+
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_399_99]: (sourceChain, txHash) => ({
|
|
738
|
+
id: progress_hook_types_1.PROGRESS_HOOK.SEND_TX_399_99,
|
|
739
|
+
title: `${friendlyChain(sourceChain)} Tx Completed`,
|
|
740
|
+
message: `Intermediate ${friendlyChain(sourceChain)} tx confirmed: ${txHash}, progressing to next phase`,
|
|
741
|
+
response: { chain: sourceChain, txHash },
|
|
742
|
+
level: 'INFO',
|
|
743
|
+
}),
|
|
730
744
|
};
|
|
731
745
|
// =============================================================================
|
|
732
746
|
// UEA Migration hooks (unchanged)
|
|
@@ -828,7 +842,7 @@ const RAW_HOOKS_MULTICHAIN = {
|
|
|
828
842
|
warningOnly: !sufficient && enforceGasCheck === false,
|
|
829
843
|
shortfall: (_d = extra === null || extra === void 0 ? void 0 : extra.shortfall) !== null && _d !== void 0 ? _d : null,
|
|
830
844
|
},
|
|
831
|
-
level: preflightLevel(sufficient
|
|
845
|
+
level: preflightLevel(sufficient),
|
|
832
846
|
};
|
|
833
847
|
},
|
|
834
848
|
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_003_04]: (required, available, shortfall, ueaAddress, pathTag, extra) => {
|