@pushchain/core 6.0.2 → 6.0.4
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 +41 -46
- 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/route-handlers.js +62 -48
- package/src/lib/orchestrator/internals/tx-transformer.js +4 -4
- package/src/lib/orchestrator/orchestrator.js +41 -14
- package/src/lib/orchestrator/orchestrator.types.d.ts +20 -4
- 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 +5 -5
- package/src/lib/progress-hook/progress-hook.types.d.ts +2 -2
- package/src/lib/progress-hook/progress-hook.types.js +1 -2
- package/src/lib/push-chain/push-chain.d.ts +8 -0
package/package.json
CHANGED
|
@@ -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
|
-
|
|
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
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
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:
|
|
300
|
-
value:
|
|
301
|
-
data:
|
|
307
|
+
to: token.address,
|
|
308
|
+
value: BigInt(0),
|
|
309
|
+
data: erc20Transfer,
|
|
302
310
|
});
|
|
303
311
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
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:
|
|
328
|
-
value:
|
|
329
|
-
data:
|
|
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 ((
|
|
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 = (
|
|
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 (((
|
|
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, (
|
|
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 ((
|
|
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
|
}
|
|
@@ -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
|
|
100
|
-
|
|
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` (
|
|
17
|
-
* throws `InsufficientUEABalanceError`
|
|
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` (
|
|
18
|
-
* throws `InsufficientUEABalanceError`
|
|
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).
|
|
@@ -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:
|
|
@@ -98,10 +98,10 @@ function reconstructProgressEvents(universalTxResponse, universalTxData) {
|
|
|
98
98
|
// omitted from reconstruction because R1 doesn't register a UniversalTx
|
|
99
99
|
// on Push Chain, so `universalTxData` is usually undefined here and we
|
|
100
100
|
// have no reliable signal to tell the three paths apart. Callers who want
|
|
101
|
-
// the full live sequence should
|
|
102
|
-
// `
|
|
103
|
-
// sendTransaction —
|
|
104
|
-
// event buffer.
|
|
101
|
+
// the full live sequence should register a progress hook at initialize
|
|
102
|
+
// time, pass `sendTransaction(params, { progressHook })`, or call
|
|
103
|
+
// `tx.progressHook(cb)` after sendTransaction — all deliver the full stream
|
|
104
|
+
// from the execute-phase event buffer.
|
|
105
105
|
const events = [];
|
|
106
106
|
const originParts = universalTxResponse.origin.split(':');
|
|
107
107
|
const chainNamespace = originParts.length >= 2 ? `${originParts[0]}:${originParts[1]}` : originParts[0];
|
|
@@ -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() {
|
|
@@ -131,9 +132,33 @@ class Orchestrator {
|
|
|
131
132
|
*/
|
|
132
133
|
execute(params, options) {
|
|
133
134
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
134
|
-
var _a, _b, _c, _d;
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
var _a, _b, _c, _d, _e;
|
|
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) });
|
|
139
|
+
}
|
|
140
|
+
const perCallHook = (_a = params.options) === null || _a === void 0 ? void 0 : _a.progressHook;
|
|
141
|
+
const originalExecuteHook = this.progressHook;
|
|
142
|
+
const currentHook = this.progressHook;
|
|
143
|
+
const shouldWrapPerCallHook = !!perCallHook &&
|
|
144
|
+
perCallHook !== currentHook &&
|
|
145
|
+
(currentHook === null || currentHook === void 0 ? void 0 : currentHook.__pushPerCallHook) !== perCallHook;
|
|
146
|
+
const attachPerCallHookForWait = (response) => {
|
|
147
|
+
if (perCallHook && response._setProgressHookNoReplay) {
|
|
148
|
+
response._setProgressHookNoReplay(perCallHook);
|
|
149
|
+
}
|
|
150
|
+
return response;
|
|
151
|
+
};
|
|
152
|
+
if (shouldWrapPerCallHook) {
|
|
153
|
+
const baseHook = this.progressHook;
|
|
154
|
+
const wrappedHook = ((event) => {
|
|
155
|
+
if (baseHook && baseHook !== perCallHook) {
|
|
156
|
+
baseHook(event);
|
|
157
|
+
}
|
|
158
|
+
perCallHook(event);
|
|
159
|
+
});
|
|
160
|
+
wrappedHook.__pushPerCallHook = perCallHook;
|
|
161
|
+
this.progressHook = wrappedHook;
|
|
137
162
|
}
|
|
138
163
|
// Snapshot the caller's active route — `executeMultiChain` recurses into
|
|
139
164
|
// this same method for R2/R3's inner Push-side execution, and without
|
|
@@ -146,7 +171,7 @@ class Orchestrator {
|
|
|
146
171
|
try {
|
|
147
172
|
detectedRoute = (0, route_detector_1.detectRoute)(params);
|
|
148
173
|
}
|
|
149
|
-
catch (
|
|
174
|
+
catch (_f) {
|
|
150
175
|
detectedRoute = route_detector_1.TransactionRoute.UOA_TO_PUSH;
|
|
151
176
|
}
|
|
152
177
|
// Don't downgrade an outer R2/R3/R4 route when the recursive inner call
|
|
@@ -164,14 +189,14 @@ class Orchestrator {
|
|
|
164
189
|
// Lazy UEA upgrade check
|
|
165
190
|
try {
|
|
166
191
|
if (!this.accountStatusCache || !this.accountStatusCache.uea.loaded) {
|
|
167
|
-
yield ((
|
|
192
|
+
yield ((_b = this.accountStatusReadyPromise) !== null && _b !== void 0 ? _b : this.getAccountStatus());
|
|
168
193
|
}
|
|
169
194
|
// If background resolved but cache still empty (timeout/error), fetch fresh
|
|
170
195
|
if (!this.accountStatusCache || !this.accountStatusCache.uea.loaded) {
|
|
171
196
|
yield this.getAccountStatus();
|
|
172
197
|
}
|
|
173
|
-
if (((
|
|
174
|
-
((
|
|
198
|
+
if (((_c = this.accountStatusCache) === null || _c === void 0 ? void 0 : _c.uea.deployed) &&
|
|
199
|
+
((_d = this.accountStatusCache) === null || _d === void 0 ? void 0 : _d.uea.requiresUpgrade)) {
|
|
175
200
|
yield this.upgradeAccount({ progressHook: this.progressHook });
|
|
176
201
|
}
|
|
177
202
|
}
|
|
@@ -179,10 +204,10 @@ class Orchestrator {
|
|
|
179
204
|
(0, internals_1.printLog)(this.ctx, `Lazy UEA upgrade check failed: ${err instanceof Error ? err.message : String(err)}. Proceeding with transaction.`);
|
|
180
205
|
}
|
|
181
206
|
// Check if this is a multi-chain request (has ChainTarget or from.chain)
|
|
182
|
-
const isMultiChain = (0, route_detector_1.isChainTarget)(params.to) || ('from' in params && ((
|
|
207
|
+
const isMultiChain = (0, route_detector_1.isChainTarget)(params.to) || ('from' in params && ((_e = params.from) === null || _e === void 0 ? void 0 : _e.chain));
|
|
183
208
|
if (isMultiChain) {
|
|
184
209
|
try {
|
|
185
|
-
return yield (0, internals_1.executeMultiChain)(this.ctx, params, this.execute.bind(this));
|
|
210
|
+
return attachPerCallHookForWait(yield (0, internals_1.executeMultiChain)(this.ctx, params, this.execute.bind(this)));
|
|
186
211
|
}
|
|
187
212
|
catch (err) {
|
|
188
213
|
// R2/R3/R4 outer catch — fires the route-correct terminal failure
|
|
@@ -218,8 +243,7 @@ class Orchestrator {
|
|
|
218
243
|
}
|
|
219
244
|
// Standard Push Chain execution (Route 1)
|
|
220
245
|
const execute = params;
|
|
221
|
-
const
|
|
222
|
-
const hasData = execute.data && execute.data !== '0x';
|
|
246
|
+
const hasData = (0, data_utils_1.hasExecutablePayloadData)(execute.data);
|
|
223
247
|
const eventBuffer = [];
|
|
224
248
|
const originalHook = this.progressHook;
|
|
225
249
|
this.progressHook = (event) => {
|
|
@@ -230,11 +254,11 @@ class Orchestrator {
|
|
|
230
254
|
try {
|
|
231
255
|
const rcb = () => this._getResponseCallbacks();
|
|
232
256
|
if (execute.funds) {
|
|
233
|
-
return !hasData
|
|
257
|
+
return attachPerCallHookForWait(!hasData
|
|
234
258
|
? yield (0, internals_1.executeFundsOnly)(this.ctx, execute, eventBuffer, rcb)
|
|
235
|
-
: yield (0, internals_1.executeFundsWithPayload)(this.ctx, execute, eventBuffer, rcb);
|
|
259
|
+
: yield (0, internals_1.executeFundsWithPayload)(this.ctx, execute, eventBuffer, rcb));
|
|
236
260
|
}
|
|
237
|
-
return yield (0, internals_1.executeStandardPayload)(this.ctx, execute, eventBuffer, rcb);
|
|
261
|
+
return attachPerCallHookForWait(yield (0, internals_1.executeStandardPayload)(this.ctx, execute, eventBuffer, rcb));
|
|
238
262
|
}
|
|
239
263
|
catch (err) {
|
|
240
264
|
const errMessage = err instanceof Error
|
|
@@ -277,6 +301,9 @@ class Orchestrator {
|
|
|
277
301
|
}
|
|
278
302
|
}
|
|
279
303
|
finally {
|
|
304
|
+
if (shouldWrapPerCallHook) {
|
|
305
|
+
this.progressHook = originalExecuteHook;
|
|
306
|
+
}
|
|
280
307
|
// Restore the caller's route so a recursive inner R1 execute doesn't
|
|
281
308
|
// leak its UOA_TO_PUSH route back to the outer R2/R3 frame.
|
|
282
309
|
this.currentRoute = previousRoute;
|
|
@@ -38,6 +38,15 @@ export interface TransactionExecutionOptions {
|
|
|
38
38
|
* - true: emit the failure hook, throw InsufficientUEABalanceError, and stop
|
|
39
39
|
*/
|
|
40
40
|
enforceGasCheck?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Optional per-call progress callback for sendTransaction().
|
|
43
|
+
* Additive with the init-time `progressHook` passed to `PushChain.initialize`:
|
|
44
|
+
* both hooks receive every `ProgressEvent` emitted during this call. The
|
|
45
|
+
* callback is also registered on the returned response for wait-phase
|
|
46
|
+
* progress without replaying already-fired events. Dedups by reference if it
|
|
47
|
+
* matches the init-time hook.
|
|
48
|
+
*/
|
|
49
|
+
progressHook?: (event: import('../progress-hook/progress-hook.types').ProgressEvent) => void;
|
|
41
50
|
}
|
|
42
51
|
export type ExecuteParams = {
|
|
43
52
|
/**
|
|
@@ -92,6 +101,12 @@ export type ExecuteParams = {
|
|
|
92
101
|
* Optional transaction behavior switches.
|
|
93
102
|
*/
|
|
94
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'];
|
|
95
110
|
/**
|
|
96
111
|
* Optional: pay gas in a specific token. If not provided, use `token` (bridge token) when present; otherwise, native token.
|
|
97
112
|
*/
|
|
@@ -184,10 +199,11 @@ export interface UniversalTxResponse {
|
|
|
184
199
|
progressHook: (callback: (event: import('../progress-hook/progress-hook.types').ProgressEvent) => void) => void;
|
|
185
200
|
/**
|
|
186
201
|
* @internal Register a wait-phase progressHook without replaying buffered
|
|
187
|
-
* events. Used by `
|
|
188
|
-
*
|
|
189
|
-
* 299-xx / 399-xx) to the
|
|
190
|
-
*
|
|
202
|
+
* events. Used by `sendTransaction(..., { progressHook })` and
|
|
203
|
+
* `trackTransaction()` to auto-attach the caller's per-call progressHook so
|
|
204
|
+
* `.wait()` can deliver wait-phase events (209-xx / 299-xx / 399-xx) to the
|
|
205
|
+
* same callback — without re-emitting the execute/reconstructed stream that
|
|
206
|
+
* already fired.
|
|
191
207
|
*/
|
|
192
208
|
_setProgressHookNoReplay?: (callback: (event: import('../progress-hook/progress-hook.types').ProgressEvent) => void) => void;
|
|
193
209
|
type: string;
|
|
@@ -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)
|
|
@@ -342,7 +342,7 @@ const RAW_HOOKS_R2 = {
|
|
|
342
342
|
warningOnly: !sufficient && enforceGasCheck === false,
|
|
343
343
|
shortfall: (_d = extra === null || extra === void 0 ? void 0 : extra.shortfall) !== null && _d !== void 0 ? _d : null,
|
|
344
344
|
},
|
|
345
|
-
level: preflightLevel(sufficient
|
|
345
|
+
level: preflightLevel(sufficient),
|
|
346
346
|
};
|
|
347
347
|
},
|
|
348
348
|
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_203_04]: (required, available, shortfall, ueaAddress, pathTag, extra) => {
|
|
@@ -560,7 +560,7 @@ const RAW_HOOKS_R3 = {
|
|
|
560
560
|
warningOnly: !sufficient && enforceGasCheck === false,
|
|
561
561
|
shortfall: (_d = extra === null || extra === void 0 ? void 0 : extra.shortfall) !== null && _d !== void 0 ? _d : null,
|
|
562
562
|
},
|
|
563
|
-
level: preflightLevel(sufficient
|
|
563
|
+
level: preflightLevel(sufficient),
|
|
564
564
|
};
|
|
565
565
|
},
|
|
566
566
|
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_303_05]: (required, available, shortfall, ueaAddress, pathTag, extra) => {
|
|
@@ -828,7 +828,7 @@ const RAW_HOOKS_MULTICHAIN = {
|
|
|
828
828
|
warningOnly: !sufficient && enforceGasCheck === false,
|
|
829
829
|
shortfall: (_d = extra === null || extra === void 0 ? void 0 : extra.shortfall) !== null && _d !== void 0 ? _d : null,
|
|
830
830
|
},
|
|
831
|
-
level: preflightLevel(sufficient
|
|
831
|
+
level: preflightLevel(sufficient),
|
|
832
832
|
};
|
|
833
833
|
},
|
|
834
834
|
[progress_hook_types_1.PROGRESS_HOOK.SEND_TX_003_04]: (required, available, shortfall, ueaAddress, pathTag, extra) => {
|
|
@@ -68,7 +68,7 @@ export declare enum PROGRESS_HOOK {
|
|
|
68
68
|
SEND_TX_303_03_01 = "SEND-TX-303-03-01",// Sizer: Case A (< $1, padded)
|
|
69
69
|
SEND_TX_303_03_02 = "SEND-TX-303-03-02",// Sizer: Case B ($1–$10, happy path)
|
|
70
70
|
SEND_TX_303_03_03 = "SEND-TX-303-03-03",// Sizer: Case C (> $10, split + overflow bridge)
|
|
71
|
-
SEND_TX_303_04 = "SEND-TX-303-04",// R3 pre-flight balance check (INFO
|
|
71
|
+
SEND_TX_303_04 = "SEND-TX-303-04",// R3 pre-flight balance check (INFO when sufficient, WARNING when short)
|
|
72
72
|
SEND_TX_303_05 = "SEND-TX-303-05",// R3 pre-flight FAILED (ERROR, terminal precursor before 399-02)
|
|
73
73
|
SEND_TX_303_06 = "SEND-TX-303-06",// R3 SVM warn-threshold tripped (INFO, no action)
|
|
74
74
|
SEND_TX_304_01 = "SEND-TX-304-01",
|
|
@@ -87,7 +87,7 @@ export declare enum PROGRESS_HOOK {
|
|
|
87
87
|
SEND_TX_001 = "SEND-TX-001",
|
|
88
88
|
SEND_TX_002_01 = "SEND-TX-002-01",
|
|
89
89
|
SEND_TX_002_99_99 = "SEND-TX-002-99-99",
|
|
90
|
-
SEND_TX_003_03 = "SEND-TX-003-03",// Cascade pre-flight balance check (INFO
|
|
90
|
+
SEND_TX_003_03 = "SEND-TX-003-03",// Cascade pre-flight balance check (INFO when sufficient, WARNING when short)
|
|
91
91
|
SEND_TX_003_04 = "SEND-TX-003-04",// Cascade pre-flight FAILED (ERROR, terminal precursor before 999-02)
|
|
92
92
|
SEND_TX_003_05 = "SEND-TX-003-05",// Cascade SVM warn-threshold tripped (INFO, no action)
|
|
93
93
|
SEND_TX_999_01 = "SEND-TX-999-01",
|
|
@@ -37,8 +37,7 @@ var PROGRESS_HOOK;
|
|
|
37
37
|
PROGRESS_HOOK["SEND_TX_202_02"] = "SEND-TX-202-02";
|
|
38
38
|
PROGRESS_HOOK["SEND_TX_203_01"] = "SEND-TX-203-01";
|
|
39
39
|
PROGRESS_HOOK["SEND_TX_203_02"] = "SEND-TX-203-02";
|
|
40
|
-
// Pre-flight balance check (203-03 INFO when sufficient, WARNING when
|
|
41
|
-
// short but enforceGasCheck=false, ERROR when enforceGasCheck=true;
|
|
40
|
+
// Pre-flight balance check (203-03 INFO when sufficient, WARNING when short;
|
|
42
41
|
// 203-04 ERROR terminal precursor on enforced shortfall;
|
|
43
42
|
// 203-05 INFO SVM warn-threshold tripped).
|
|
44
43
|
// 203 bucket choice is temporal (sits between 203-02 CEA-resolved and 204-01 sign),
|
|
@@ -71,6 +71,14 @@ export declare class PushChain {
|
|
|
71
71
|
* @param options.enforceGasCheck - Defaults to false. When true, the
|
|
72
72
|
* SDK stops on pre-flight gas/balance shortfall instead of warning
|
|
73
73
|
* and proceeding.
|
|
74
|
+
* @param params.progressHook - Optional per-call progress callback.
|
|
75
|
+
* Alias for `sendTransaction(params, { progressHook })`.
|
|
76
|
+
* @param options.progressHook - Optional per-call progress callback.
|
|
77
|
+
* Additive with the init-time `progressHook` passed to `initialize`:
|
|
78
|
+
* both hooks receive every `ProgressEvent` emitted during this call.
|
|
79
|
+
* The callback is also registered on the returned response for wait()
|
|
80
|
+
* progress without replaying already-fired events. Dedups by reference
|
|
81
|
+
* if it matches the init-time hook.
|
|
74
82
|
*/
|
|
75
83
|
sendTransaction: Orchestrator['execute'];
|
|
76
84
|
/**
|