@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
|
@@ -10,12 +10,8 @@
|
|
|
10
10
|
* Unknown selectors fall through with `kind: 'unknown'` so callers can log
|
|
11
11
|
* them at INFO and grow the table from real reverts.
|
|
12
12
|
*
|
|
13
|
-
* The selector→name mappings below
|
|
14
|
-
* production
|
|
15
|
-
* parameterless signatures (e.g. `keccak256("InsufficientBalance()")` =
|
|
16
|
-
* `0x01e1e567`) does NOT reproduce the listed selectors, so the deployed-
|
|
17
|
-
* source mapping is still unverified. Names and hints are worded as
|
|
18
|
-
* "likely cause" until the bytecode-source trace lands.
|
|
13
|
+
* The selector→name mappings below come from source-verified custom errors
|
|
14
|
+
* where available, with production/e2e observations kept as provenance.
|
|
19
15
|
*/
|
|
20
16
|
export interface KnownErrorSelector {
|
|
21
17
|
/** Best-effort error name. Worded as a likely cause until source-traced. */
|
|
@@ -11,12 +11,8 @@
|
|
|
11
11
|
* Unknown selectors fall through with `kind: 'unknown'` so callers can log
|
|
12
12
|
* them at INFO and grow the table from real reverts.
|
|
13
13
|
*
|
|
14
|
-
* The selector→name mappings below
|
|
15
|
-
* production
|
|
16
|
-
* parameterless signatures (e.g. `keccak256("InsufficientBalance()")` =
|
|
17
|
-
* `0x01e1e567`) does NOT reproduce the listed selectors, so the deployed-
|
|
18
|
-
* source mapping is still unverified. Names and hints are worded as
|
|
19
|
-
* "likely cause" until the bytecode-source trace lands.
|
|
14
|
+
* The selector→name mappings below come from source-verified custom errors
|
|
15
|
+
* where available, with production/e2e observations kept as provenance.
|
|
20
16
|
*/
|
|
21
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
18
|
exports.ERROR_STRING_SELECTOR = exports.KNOWN_ERROR_SELECTORS = void 0;
|
|
@@ -36,10 +32,14 @@ exports.KNOWN_ERROR_SELECTORS = {
|
|
|
36
32
|
},
|
|
37
33
|
'0xf4d678b8': {
|
|
38
34
|
name: 'InsufficientBalance',
|
|
39
|
-
hint: 'Likely cause:
|
|
40
|
-
'For
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
hint: 'Likely cause: the executing account does not hold enough of the token being moved. ' +
|
|
36
|
+
'For Push outbounds, verify the UEA PRC-20 burn-token balance. For CEA→Push routes, verify the source-chain CEA balance.',
|
|
37
|
+
provenance: 'CommonErrors/CEAErrors.InsufficientBalance(); production e2e: e2e-2026-04-16T16-27-58-082Z.log:342',
|
|
38
|
+
},
|
|
39
|
+
'0xb4fa3fb3': {
|
|
40
|
+
name: 'InvalidInput',
|
|
41
|
+
hint: 'Likely cause: contract-level input validation failed. For CEA self-calls, the multicall entry must use value=0 and the encoded sendUniversalTxToUEA amount/revertRecipient must be valid.',
|
|
42
|
+
provenance: 'CommonErrors/CEAErrors.InvalidInput(); observed while replaying failed Route 3 CEA self-call tx 0x6fc0635d76edae0659ff131fd4bbf3349e01946708ce56dc2668d878f34a6077',
|
|
43
43
|
},
|
|
44
44
|
'0x66f9d09e': {
|
|
45
45
|
name: 'GasLimitBelowBase',
|
|
@@ -52,7 +52,7 @@ export interface InsufficientUEABalanceErrorOpts {
|
|
|
52
52
|
shortfall: bigint;
|
|
53
53
|
ueaAddress: `0x${string}`;
|
|
54
54
|
pathTag: PreflightPathTag;
|
|
55
|
-
/** 'NATIVE' =
|
|
55
|
+
/** 'NATIVE' = native PC shortfall; 'PRC20' = burn-token shortfall. */
|
|
56
56
|
reason?: PreflightShortfallReason;
|
|
57
57
|
/** Burn token address (only set when reason === 'PRC20'). */
|
|
58
58
|
burnToken?: `0x${string}`;
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.InsufficientUEABalanceError = exports.PushChainExecutionError = void 0;
|
|
14
|
+
const formatters_1 = require("../../formatters");
|
|
14
15
|
/**
|
|
15
16
|
* Typed error for Route 1 Push Chain tx failures. Thrown by
|
|
16
17
|
* `extractPcTxAndTransform` when the final pcTx commits with `status === 'FAILED'`,
|
|
@@ -28,7 +29,7 @@ exports.InsufficientUEABalanceError = exports.PushChainExecutionError = void 0;
|
|
|
28
29
|
*/
|
|
29
30
|
class PushChainExecutionError extends Error {
|
|
30
31
|
constructor(message, opts = {}) {
|
|
31
|
-
super(message);
|
|
32
|
+
super((0, formatters_1.normalizePcInsufficientFundsError)(message));
|
|
32
33
|
this.code = 'PUSH_CHAIN_EXECUTION_FAILED';
|
|
33
34
|
this.name = 'PushChainExecutionError';
|
|
34
35
|
this.gatewayTxHash = opts.gatewayTxHash;
|
|
@@ -50,13 +51,15 @@ class InsufficientUEABalanceError extends PushChainExecutionError {
|
|
|
50
51
|
const tokenSuffix = reason === 'PRC20' && opts.burnToken
|
|
51
52
|
? ` of token ${opts.burnToken}`
|
|
52
53
|
: '';
|
|
53
|
-
const
|
|
54
|
+
const availableLabel = reason === 'PRC20' ? `${opts.available} units` : (0, formatters_1.formatPc)(opts.available);
|
|
55
|
+
const requiredLabel = reason === 'PRC20' ? `${opts.required} units` : (0, formatters_1.formatPc)(opts.required);
|
|
56
|
+
const shortfallLabel = reason === 'PRC20' ? `${opts.shortfall} units` : (0, formatters_1.formatPc)(opts.shortfall);
|
|
54
57
|
const remediation = reason === 'PRC20'
|
|
55
58
|
? `Bridge the burn token to UEA on Push Chain before retrying.`
|
|
56
|
-
: `Bridge >=${
|
|
59
|
+
: `Bridge >=${shortfallLabel} to the UEA on Push Chain before retrying.`;
|
|
57
60
|
const message = `InsufficientUEABalance [${opts.pathTag}${segLabel}:${reason}]: ` +
|
|
58
|
-
`UEA ${opts.ueaAddress} has ${
|
|
59
|
-
`outbound requires ${
|
|
61
|
+
`UEA ${opts.ueaAddress} has ${availableLabel}${tokenSuffix}; ` +
|
|
62
|
+
`outbound requires ${requiredLabel}; shortfall ${shortfallLabel}. ` +
|
|
60
63
|
remediation;
|
|
61
64
|
// Lift the structured info into the parent's decodedError so the
|
|
62
65
|
// orchestrator's outer catch can pass it straight through to the
|
|
@@ -29,6 +29,7 @@ const push_chain_tx_1 = require("./push-chain-tx");
|
|
|
29
29
|
const svm_helpers_1 = require("./svm-helpers");
|
|
30
30
|
const helpers_2 = require("./helpers");
|
|
31
31
|
const response_builder_2 = require("./response-builder");
|
|
32
|
+
const formatters_1 = require("../../formatters");
|
|
32
33
|
function executeFundsOnly(ctx, execute, eventBuffer, getResponseCallbacks) {
|
|
33
34
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
34
35
|
const transformFn = (tx, buf = []) => (0, response_builder_2.transformToUniversalTxResponse)(ctx, tx, buf, getResponseCallbacks());
|
|
@@ -139,7 +140,7 @@ function executeFundsOnlyEvm(ctx, execute, eventBuffer, transformFn, chain, rpcU
|
|
|
139
140
|
}
|
|
140
141
|
catch (err) {
|
|
141
142
|
if (!(err instanceof push_chain_tx_1.PushChainExecutionError)) {
|
|
142
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
143
|
+
const errMsg = (0, formatters_1.normalizePcInsufficientFundsError)(err instanceof Error ? err.message : String(err));
|
|
143
144
|
(0, context_2.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_02, errMsg);
|
|
144
145
|
throw new push_chain_tx_1.PushChainExecutionError(errMsg, { gatewayTxHash: txHash });
|
|
145
146
|
}
|
|
@@ -230,7 +231,7 @@ function executeFundsOnlySvm(ctx, execute, eventBuffer, transformFn, chain, rpcU
|
|
|
230
231
|
}
|
|
231
232
|
catch (err) {
|
|
232
233
|
if (!(err instanceof push_chain_tx_1.PushChainExecutionError)) {
|
|
233
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
234
|
+
const errMsg = (0, formatters_1.normalizePcInsufficientFundsError)(err instanceof Error ? err.message : String(err));
|
|
234
235
|
(0, context_2.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_02, errMsg);
|
|
235
236
|
throw new push_chain_tx_1.PushChainExecutionError(errMsg, { gatewayTxHash: txSignature });
|
|
236
237
|
}
|
|
@@ -32,6 +32,7 @@ const push_chain_tx_1 = require("./push-chain-tx");
|
|
|
32
32
|
const svm_bridge_1 = require("./svm-bridge");
|
|
33
33
|
const signing_1 = require("./signing");
|
|
34
34
|
const quote_1 = require("./quote");
|
|
35
|
+
const formatters_1 = require("../../formatters");
|
|
35
36
|
function executeFundsWithPayload(ctx, execute, eventBuffer, getResponseCallbacks) {
|
|
36
37
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
37
38
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
@@ -240,7 +241,7 @@ function executeFundsWithPayload(ctx, execute, eventBuffer, getResponseCallbacks
|
|
|
240
241
|
}
|
|
241
242
|
catch (err) {
|
|
242
243
|
if (!(err instanceof push_chain_tx_1.PushChainExecutionError)) {
|
|
243
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
244
|
+
const errMsg = (0, formatters_1.normalizePcInsufficientFundsError)(err instanceof Error ? err.message : String(err));
|
|
244
245
|
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_02, errMsg);
|
|
245
246
|
throw new push_chain_tx_1.PushChainExecutionError(errMsg, { gatewayTxHash: txHash });
|
|
246
247
|
}
|
|
@@ -16,6 +16,7 @@ const chain_1 = require("../../constants/chain");
|
|
|
16
16
|
const enums_1 = require("../../constants/enums");
|
|
17
17
|
const tx_1 = require("../../generated/v1/tx");
|
|
18
18
|
const progress_hook_types_1 = require("../../progress-hook/progress-hook.types");
|
|
19
|
+
const formatters_1 = require("../../formatters");
|
|
19
20
|
const utils_1 = require("../../utils");
|
|
20
21
|
const evm_client_1 = require("../../vm-client/evm-client");
|
|
21
22
|
const payload_builders_1 = require("../payload-builders");
|
|
@@ -103,7 +104,7 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
|
|
|
103
104
|
catch (err) {
|
|
104
105
|
// Push Chain broadcast failed. Wallet rejection surfaces as 104-04;
|
|
105
106
|
// everything else (RPC fail, on-chain revert) as 199-02.
|
|
106
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
107
|
+
const errMsg = (0, formatters_1.normalizePcInsufficientFundsError)(err instanceof Error ? err.message : String(err));
|
|
107
108
|
const { isUserDecline } = (0, progress_hook_1.classifyDeclineError)(errMsg);
|
|
108
109
|
(0, context_1.fireProgressHook)(ctx, isUserDecline ? progress_hook_types_1.PROGRESS_HOOK.SEND_TX_104_04 : progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_02, errMsg);
|
|
109
110
|
// Mark that a terminal-ish error hook has already fired so the
|
|
@@ -266,7 +267,7 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
|
|
|
266
267
|
// Wallet decline, contract revert during sign, or RPC failure — the
|
|
267
268
|
// 104-04 builder's classifyDeclineError heuristic picks the right
|
|
268
269
|
// copy (real decline → "Verification Declined"; else "Signature Failed").
|
|
269
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
270
|
+
const errMsg = (0, formatters_1.normalizePcInsufficientFundsError)(err instanceof Error ? err.message : String(err));
|
|
270
271
|
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_104_04, errMsg);
|
|
271
272
|
throw err;
|
|
272
273
|
}
|
|
@@ -352,15 +353,15 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
|
|
|
352
353
|
const maxTransferable = funds + maxFromDeposit;
|
|
353
354
|
maxTransferableNote =
|
|
354
355
|
`Max transferable right now (at $1000 cap, pool-limited): ` +
|
|
355
|
-
`~${(
|
|
356
|
-
`(UEA balance ${(
|
|
357
|
-
`pool-safe deposit ${(
|
|
356
|
+
`~${(0, formatters_1.formatPc)(maxTransferable, 4)} ` +
|
|
357
|
+
`(UEA balance ${(0, formatters_1.formatPc)(funds, 4)} + ` +
|
|
358
|
+
`pool-safe deposit ${(0, formatters_1.formatPc)(maxFromDeposit, 4)} - gas).`;
|
|
358
359
|
(0, context_1.printLog)(ctx, `Fee-lock capacity: ${maxTransferableNote}`);
|
|
359
360
|
}
|
|
360
361
|
}
|
|
361
|
-
throw new Error(`Insufficient deposit: the fee-lock will deposit ~${(
|
|
362
|
-
`but the transaction requires ~${(
|
|
363
|
-
`(shortfall: ~${(
|
|
362
|
+
throw new Error(`Insufficient deposit: the fee-lock will deposit ~${(0, formatters_1.formatPc)(safeUPC, 4)} ` +
|
|
363
|
+
`but the transaction requires ~${(0, formatters_1.formatPc)(requiredFunds, 4)} ` +
|
|
364
|
+
`(shortfall: ~${(0, formatters_1.formatPc)(shortfall, 4)}). ` +
|
|
364
365
|
`The fee-lock deposit is capped at $1000 USD. ` +
|
|
365
366
|
(maxTransferableNote ? maxTransferableNote + ' ' : '') +
|
|
366
367
|
`Reduce the transfer value or pre-fund the UEA (${UEA}) on Push Chain.`);
|
|
@@ -412,7 +413,7 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
|
|
|
412
413
|
}
|
|
413
414
|
catch (err) {
|
|
414
415
|
if (!(err instanceof push_chain_tx_1.PushChainExecutionError)) {
|
|
415
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
416
|
+
const errMsg = (0, formatters_1.normalizePcInsufficientFundsError)(err instanceof Error ? err.message : String(err));
|
|
416
417
|
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_02, errMsg);
|
|
417
418
|
throw new push_chain_tx_1.PushChainExecutionError(errMsg, { gatewayTxHash: feeLockTxHash });
|
|
418
419
|
}
|
|
@@ -446,7 +447,7 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
|
|
|
446
447
|
// exhaustion). Surface terminal 199-02 before re-throwing so the stream
|
|
447
448
|
// ends with the spec'd error hook. Typed PushChainExecutionError lets
|
|
448
449
|
// callers classify via instanceof without message sniffing.
|
|
449
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
450
|
+
const errMsg = (0, formatters_1.normalizePcInsufficientFundsError)(err instanceof Error ? err.message : String(err));
|
|
450
451
|
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_199_02, errMsg);
|
|
451
452
|
if (err instanceof push_chain_tx_1.PushChainExecutionError)
|
|
452
453
|
throw err;
|
|
@@ -64,6 +64,31 @@ const UNISWAP_V3_FACTORY_ABI = [
|
|
|
64
64
|
stateMutability: 'view',
|
|
65
65
|
},
|
|
66
66
|
];
|
|
67
|
+
const UNISWAP_V3_QUOTER_EXACT_OUTPUT_ABI = [
|
|
68
|
+
{
|
|
69
|
+
type: 'function',
|
|
70
|
+
name: 'quoteExactOutputSingle',
|
|
71
|
+
inputs: [
|
|
72
|
+
{
|
|
73
|
+
type: 'tuple',
|
|
74
|
+
components: [
|
|
75
|
+
{ name: 'tokenIn', type: 'address' },
|
|
76
|
+
{ name: 'tokenOut', type: 'address' },
|
|
77
|
+
{ name: 'amount', type: 'uint256' },
|
|
78
|
+
{ name: 'fee', type: 'uint24' },
|
|
79
|
+
{ name: 'sqrtPriceLimitX96', type: 'uint160' },
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
outputs: [
|
|
84
|
+
{ name: 'amountIn', type: 'uint256' },
|
|
85
|
+
{ name: 'sqrtPriceX96After', type: 'uint160' },
|
|
86
|
+
{ name: 'initializedTicksCrossed', type: 'uint32' },
|
|
87
|
+
{ name: 'gasEstimate', type: 'uint256' },
|
|
88
|
+
],
|
|
89
|
+
stateMutability: 'view',
|
|
90
|
+
},
|
|
91
|
+
];
|
|
67
92
|
const UNIVERSAL_CORE_SWAP_HELPERS_ABI = [
|
|
68
93
|
{ type: 'function', name: 'WPC', inputs: [], outputs: [{ name: '', type: 'address', internalType: 'address' }], stateMutability: 'view' },
|
|
69
94
|
{ type: 'function', name: 'uniswapV3Factory', inputs: [], outputs: [{ name: '', type: 'address', internalType: 'address' }], stateMutability: 'view' },
|
|
@@ -133,7 +158,7 @@ function ensureErc20Allowance(ctx, evmClient, tokenAddress, spender, requiredAmo
|
|
|
133
158
|
// ============================================================================
|
|
134
159
|
function queryOutboundGasFee(ctx, prc20Token, gasLimit, destinationChain) {
|
|
135
160
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
136
|
-
var _a, _b;
|
|
161
|
+
var _a, _b, _c;
|
|
137
162
|
const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
|
|
138
163
|
const pushChain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
|
|
139
164
|
const rpcUrl = ((_b = (_a = chain_1.CHAIN_INFO[pushChain]) === null || _a === void 0 ? void 0 : _a.defaultRPC) === null || _b === void 0 ? void 0 : _b[0]) || 'unknown';
|
|
@@ -143,13 +168,13 @@ function queryOutboundGasFee(ctx, prc20Token, gasLimit, destinationChain) {
|
|
|
143
168
|
universalCoreAddress = yield ctx.pushClient.readContract({
|
|
144
169
|
address: gatewayPcAddress,
|
|
145
170
|
abi: abi_1.UNIVERSAL_GATEWAY_PC,
|
|
146
|
-
functionName: '
|
|
171
|
+
functionName: 'universalCore',
|
|
147
172
|
args: [],
|
|
148
173
|
});
|
|
149
|
-
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 2]
|
|
174
|
+
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 2] universalCore resolved to: ${universalCoreAddress}`);
|
|
150
175
|
}
|
|
151
176
|
catch (err) {
|
|
152
|
-
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 2] FAILED to read
|
|
177
|
+
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 2] FAILED to read universalCore: ${err instanceof Error ? err.message : String(err)}`);
|
|
153
178
|
throw err;
|
|
154
179
|
}
|
|
155
180
|
const callData = (0, viem_1.encodeFunctionData)({
|
|
@@ -163,6 +188,7 @@ function queryOutboundGasFee(ctx, prc20Token, gasLimit, destinationChain) {
|
|
|
163
188
|
let gasFee;
|
|
164
189
|
let protocolFee;
|
|
165
190
|
let gasPrice = BigInt(0);
|
|
191
|
+
let gasLimitUsed = gasLimit;
|
|
166
192
|
try {
|
|
167
193
|
const result = yield ctx.pushClient.readContract({
|
|
168
194
|
address: universalCoreAddress,
|
|
@@ -174,7 +200,8 @@ function queryOutboundGasFee(ctx, prc20Token, gasLimit, destinationChain) {
|
|
|
174
200
|
gasFee = result[1];
|
|
175
201
|
protocolFee = result[2];
|
|
176
202
|
gasPrice = result[3];
|
|
177
|
-
(
|
|
203
|
+
gasLimitUsed = (_c = result[5]) !== null && _c !== void 0 ? _c : gasLimit;
|
|
204
|
+
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 4] success: gasToken=${gasToken}, gasFee=${gasFee}, protocolFee=${protocolFee}, gasPrice=${gasPrice}, gasLimitUsed=${gasLimitUsed}`);
|
|
178
205
|
}
|
|
179
206
|
catch (err) {
|
|
180
207
|
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 3] FAILED: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -205,7 +232,7 @@ function queryOutboundGasFee(ctx, prc20Token, gasLimit, destinationChain) {
|
|
|
205
232
|
nativeValueForGas = protocolFee + gasFee * GAS_FEE_BUFFER_MULTIPLIER;
|
|
206
233
|
(0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 5] no destinationChain provided; legacy 1M buffer: nativeValueForGas=${nativeValueForGas}`);
|
|
207
234
|
}
|
|
208
|
-
return { gasToken, gasFee, protocolFee, nativeValueForGas, gasPrice, universalCoreAddress, sizing };
|
|
235
|
+
return { gasToken, gasFee, protocolFee, nativeValueForGas, gasPrice, gasLimitUsed, universalCoreAddress, sizing };
|
|
209
236
|
});
|
|
210
237
|
}
|
|
211
238
|
// ============================================================================
|
|
@@ -219,7 +246,19 @@ function queryOutboundGasFee(ctx, prc20Token, gasLimit, destinationChain) {
|
|
|
219
246
|
*/
|
|
220
247
|
function estimateNativeValueForSwap(ctx, universalCoreAddress, gasToken, gasFee, accountBalance) {
|
|
221
248
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
222
|
-
|
|
249
|
+
var _a, _b;
|
|
250
|
+
// 2.2x safety buffer applied to the pool quote; excess is refunded by
|
|
251
|
+
// swapAndBurnGas. Composed of a 2x pool-slippage cushion plus 10%
|
|
252
|
+
// headroom that used to live in the R2 route-handler callers (×110/100
|
|
253
|
+
// after this function returned). Folded into one place here so the cap
|
|
254
|
+
// branch below correctly bounds the FINAL inflated value — the previous
|
|
255
|
+
// arrangement (outer ×1.10 on top of an inner cap that returned
|
|
256
|
+
// `balance - GAS_RESERVE`) caused a deterministic preflight failure
|
|
257
|
+
// whenever the cap fired: required = 1.10 × (balance − 3 PC) + 3 PC ≈
|
|
258
|
+
// balance × 1.10 − 0.3 PC > balance for any non-trivial balance. See
|
|
259
|
+
// preflight.ts:215.
|
|
260
|
+
const SWAP_BUFFER_NUM = BigInt(22);
|
|
261
|
+
const SWAP_BUFFER_DEN = BigInt(10);
|
|
223
262
|
const BALANCE_FALLBACK_DIVISOR = BigInt(10); // 10% of balance as fallback
|
|
224
263
|
const GAS_RESERVE = BigInt(3e18); // 3 UPC reserve for tx overhead
|
|
225
264
|
try {
|
|
@@ -248,6 +287,34 @@ function estimateNativeValueForSwap(ctx, universalCoreAddress, gasToken, gasFee,
|
|
|
248
287
|
(0, context_1.printLog)(ctx, `estimateNativeValueForSwap — no fee tier for gasToken, using balance fallback`);
|
|
249
288
|
return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
|
|
250
289
|
}
|
|
290
|
+
const pushChain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
|
|
291
|
+
const quoterAddress = (_b = (_a = chain_1.CHAIN_INFO[pushChain]) === null || _a === void 0 ? void 0 : _a.dex) === null || _b === void 0 ? void 0 : _b.uniV3QuoterV2;
|
|
292
|
+
if (quoterAddress && !quoterAddress.startsWith('0xTBD')) {
|
|
293
|
+
try {
|
|
294
|
+
const quote = yield ctx.pushClient.readContract({
|
|
295
|
+
address: quoterAddress,
|
|
296
|
+
abi: UNISWAP_V3_QUOTER_EXACT_OUTPUT_ABI,
|
|
297
|
+
functionName: 'quoteExactOutputSingle',
|
|
298
|
+
args: [
|
|
299
|
+
{
|
|
300
|
+
tokenIn: wpcAddress,
|
|
301
|
+
tokenOut: gasToken,
|
|
302
|
+
amount: gasFee,
|
|
303
|
+
fee: feeTier,
|
|
304
|
+
sqrtPriceLimitX96: BigInt(0),
|
|
305
|
+
},
|
|
306
|
+
],
|
|
307
|
+
});
|
|
308
|
+
const exactWpcNeeded = quote[0];
|
|
309
|
+
const result = (exactWpcNeeded * SWAP_BUFFER_NUM) / SWAP_BUFFER_DEN;
|
|
310
|
+
(0, context_1.printLog)(ctx, `estimateNativeValueForSwap — exactOutput quoter=${quoterAddress}, ` +
|
|
311
|
+
`wpcNeeded=${exactWpcNeeded}, withBuffer(2.2x)=${result}`);
|
|
312
|
+
return capSwapEstimate(result, accountBalance, GAS_RESERVE);
|
|
313
|
+
}
|
|
314
|
+
catch (quoteErr) {
|
|
315
|
+
(0, context_1.printLog)(ctx, `estimateNativeValueForSwap — exactOutput quote failed: ${quoteErr instanceof Error ? quoteErr.message : String(quoteErr)}, falling back to slot0 price`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
251
318
|
// Get pool address from factory
|
|
252
319
|
const poolAddress = yield ctx.pushClient.readContract({
|
|
253
320
|
address: factoryAddress,
|
|
@@ -285,17 +352,10 @@ function estimateNativeValueForSwap(ctx, universalCoreAddress, gasToken, gasFee,
|
|
|
285
352
|
// price = gasToken_per_WPC → wpcNeeded = gasFee / price
|
|
286
353
|
wpcNeeded = (gasFee * Q192) / priceNum;
|
|
287
354
|
}
|
|
288
|
-
const result = wpcNeeded *
|
|
355
|
+
const result = (wpcNeeded * SWAP_BUFFER_NUM) / SWAP_BUFFER_DEN;
|
|
289
356
|
(0, context_1.printLog)(ctx, `estimateNativeValueForSwap — pool=${poolAddress}, sqrtPriceX96=${sqrtPriceX96}, ` +
|
|
290
|
-
`wpcNeeded=${wpcNeeded}, withBuffer(2x)=${result}`);
|
|
291
|
-
|
|
292
|
-
if (accountBalance > result + GAS_RESERVE) {
|
|
293
|
-
return result;
|
|
294
|
-
}
|
|
295
|
-
else if (accountBalance > GAS_RESERVE) {
|
|
296
|
-
return accountBalance - GAS_RESERVE;
|
|
297
|
-
}
|
|
298
|
-
return result; // let caller decide if balance is too low
|
|
357
|
+
`wpcNeeded=${wpcNeeded}, withBuffer(2.2x)=${result}`);
|
|
358
|
+
return capSwapEstimate(result, accountBalance, GAS_RESERVE);
|
|
299
359
|
}
|
|
300
360
|
catch (err) {
|
|
301
361
|
(0, context_1.printLog)(ctx, `estimateNativeValueForSwap — failed: ${err instanceof Error ? err.message : String(err)}, using balance fallback`);
|
|
@@ -303,6 +363,15 @@ function estimateNativeValueForSwap(ctx, universalCoreAddress, gasToken, gasFee,
|
|
|
303
363
|
}
|
|
304
364
|
});
|
|
305
365
|
}
|
|
366
|
+
function capSwapEstimate(result, accountBalance, reserve) {
|
|
367
|
+
if (accountBalance > result + reserve) {
|
|
368
|
+
return result;
|
|
369
|
+
}
|
|
370
|
+
if (accountBalance > reserve) {
|
|
371
|
+
return accountBalance - reserve;
|
|
372
|
+
}
|
|
373
|
+
return result; // let caller decide if balance is too low
|
|
374
|
+
}
|
|
306
375
|
function balanceFallback(balance, divisor, reserve) {
|
|
307
376
|
const fraction = balance / divisor;
|
|
308
377
|
if (balance > fraction + reserve)
|
|
@@ -323,13 +392,13 @@ function queryRescueGasFee(ctx, prc20Token, destinationChain) {
|
|
|
323
392
|
universalCoreAddress = yield ctx.pushClient.readContract({
|
|
324
393
|
address: gatewayPcAddress,
|
|
325
394
|
abi: abi_1.UNIVERSAL_GATEWAY_PC,
|
|
326
|
-
functionName: '
|
|
395
|
+
functionName: 'universalCore',
|
|
327
396
|
args: [],
|
|
328
397
|
});
|
|
329
|
-
(0, context_1.printLog)(ctx, `queryRescueGasFee —
|
|
398
|
+
(0, context_1.printLog)(ctx, `queryRescueGasFee — universalCore resolved to: ${universalCoreAddress}`);
|
|
330
399
|
}
|
|
331
400
|
catch (err) {
|
|
332
|
-
(0, context_1.printLog)(ctx, `queryRescueGasFee — FAILED to read
|
|
401
|
+
(0, context_1.printLog)(ctx, `queryRescueGasFee — FAILED to read universalCore: ${err instanceof Error ? err.message : String(err)}`);
|
|
333
402
|
throw err;
|
|
334
403
|
}
|
|
335
404
|
let gasToken;
|
|
@@ -495,7 +564,7 @@ function estimateDepositFromLockedNative(ctx, nativeAmountForLocker, prc20Token)
|
|
|
495
564
|
const universalCoreAddress = yield ctx.pushClient.readContract({
|
|
496
565
|
address: gatewayPcAddress,
|
|
497
566
|
abi: abi_1.UNIVERSAL_GATEWAY_PC,
|
|
498
|
-
functionName: '
|
|
567
|
+
functionName: 'universalCore',
|
|
499
568
|
args: [],
|
|
500
569
|
});
|
|
501
570
|
const [wpcAddress, feeTier] = yield Promise.all([
|
|
@@ -587,7 +656,7 @@ function estimateNativeForDesiredDeposit(ctx, desiredWpc, prc20Token) {
|
|
|
587
656
|
const universalCoreAddress = yield ctx.pushClient.readContract({
|
|
588
657
|
address: gatewayPcAddress,
|
|
589
658
|
abi: abi_1.UNIVERSAL_GATEWAY_PC,
|
|
590
|
-
functionName: '
|
|
659
|
+
functionName: 'universalCore',
|
|
591
660
|
args: [],
|
|
592
661
|
});
|
|
593
662
|
const [wpcAddress, feeTier] = yield Promise.all([
|
|
@@ -9,9 +9,10 @@ import type { OrchestratorContext } from './context';
|
|
|
9
9
|
/** Chains that support gateway operations (multicall, funds bridging, etc.) */
|
|
10
10
|
export declare const SUPPORTED_GATEWAY_CHAINS: CHAIN[];
|
|
11
11
|
export declare function isPushChain(chain: CHAIN): boolean;
|
|
12
|
+
export { toExternalTxHashDisplay } from '../../utils/external-tx-hash';
|
|
12
13
|
export declare function getPushChainForNetwork(pushNetwork: PUSH_NETWORK): CHAIN;
|
|
13
14
|
export declare function getChainNamespace(chain: CHAIN): string;
|
|
14
|
-
export
|
|
15
|
+
export { chainFromNamespace } from '../../utils/external-tx-hash';
|
|
15
16
|
export declare function getNativePRC20ForChain(targetChain: CHAIN, pushNetwork: PUSH_NETWORK): `0x${string}`;
|
|
16
17
|
export declare function getUniversalGatewayPCAddress(): `0x${string}`;
|
|
17
18
|
/**
|
|
@@ -5,11 +5,10 @@
|
|
|
5
5
|
* These have minimal dependencies and are used across multiple submodules.
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.SUPPORTED_GATEWAY_CHAINS = void 0;
|
|
8
|
+
exports.chainFromNamespace = exports.toExternalTxHashDisplay = exports.SUPPORTED_GATEWAY_CHAINS = void 0;
|
|
9
9
|
exports.isPushChain = isPushChain;
|
|
10
10
|
exports.getPushChainForNetwork = getPushChainForNetwork;
|
|
11
11
|
exports.getChainNamespace = getChainNamespace;
|
|
12
|
-
exports.chainFromNamespace = chainFromNamespace;
|
|
13
12
|
exports.getNativePRC20ForChain = getNativePRC20ForChain;
|
|
14
13
|
exports.getUniversalGatewayPCAddress = getUniversalGatewayPCAddress;
|
|
15
14
|
exports.validateFeeLockTxHash = validateFeeLockTxHash;
|
|
@@ -38,6 +37,14 @@ function isPushChain(chain) {
|
|
|
38
37
|
chain === enums_1.CHAIN.PUSH_TESTNET_DONUT ||
|
|
39
38
|
chain === enums_1.CHAIN.PUSH_LOCALNET);
|
|
40
39
|
}
|
|
40
|
+
// `toExternalTxHashDisplay` moved to ../../utils/external-tx-hash so the
|
|
41
|
+
// detector module can use it without back-importing from orchestrator/internals
|
|
42
|
+
// (inbound-tracker.ts already imports universal-tx-detector — a back-import
|
|
43
|
+
// from detector would create a cross-layer tangle). Re-exported here so
|
|
44
|
+
// existing call sites (outbound-sync.ts / response-builder.ts / cascade.ts)
|
|
45
|
+
// keep their current import path unchanged.
|
|
46
|
+
var external_tx_hash_1 = require("../../utils/external-tx-hash");
|
|
47
|
+
Object.defineProperty(exports, "toExternalTxHashDisplay", { enumerable: true, get: function () { return external_tx_hash_1.toExternalTxHashDisplay; } });
|
|
41
48
|
function getPushChainForNetwork(pushNetwork) {
|
|
42
49
|
if (pushNetwork === enums_1.PUSH_NETWORK.MAINNET) {
|
|
43
50
|
return enums_1.CHAIN.PUSH_MAINNET;
|
|
@@ -55,15 +62,10 @@ function getChainNamespace(chain) {
|
|
|
55
62
|
const namespace = chain_1.VM_NAMESPACE[vm];
|
|
56
63
|
return `${namespace}:${chainId}`;
|
|
57
64
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return chainKey;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
65
|
+
// Moved to ../../utils/external-tx-hash alongside `toExternalTxHashDisplay`
|
|
66
|
+
// so both the orchestrator and the detector module share one implementation.
|
|
67
|
+
var external_tx_hash_2 = require("../../utils/external-tx-hash");
|
|
68
|
+
Object.defineProperty(exports, "chainFromNamespace", { enumerable: true, get: function () { return external_tx_hash_2.chainFromNamespace; } });
|
|
67
69
|
function getNativePRC20ForChain(targetChain, pushNetwork) {
|
|
68
70
|
const synthetics = chain_1.SYNTHETIC_PUSH_ERC20[pushNetwork];
|
|
69
71
|
switch (targetChain) {
|
|
@@ -140,6 +142,7 @@ function toExecuteParams(params) {
|
|
|
140
142
|
data: params.data,
|
|
141
143
|
funds: params.funds,
|
|
142
144
|
gasLimit: params.gasLimit,
|
|
145
|
+
maxPCForGas: params.maxPCForGas,
|
|
143
146
|
maxFeePerGas: params.maxFeePerGas,
|
|
144
147
|
maxPriorityFeePerGas: params.maxPriorityFeePerGas,
|
|
145
148
|
deadline: params.deadline,
|
|
@@ -20,6 +20,7 @@ const types_1 = require("../../generated/uexecutor/v2/types");
|
|
|
20
20
|
const context_1 = require("./context");
|
|
21
21
|
const detector_1 = require("../../universal-tx-detector/detector");
|
|
22
22
|
const child_inbounds_1 = require("../../universal-tx-detector/child-inbounds");
|
|
23
|
+
const formatters_1 = require("../../formatters");
|
|
23
24
|
const TERMINAL_SUCCESS_STATUSES = new Set([
|
|
24
25
|
types_1.UniversalTxStatus.INBOUND_SUCCESS,
|
|
25
26
|
types_1.UniversalTxStatus.PC_EXECUTED_SUCCESS,
|
|
@@ -205,8 +206,9 @@ function waitForInboundPushTx(ctx_1, outboundExternalTxHash_1, sourceChain_1) {
|
|
|
205
206
|
}
|
|
206
207
|
}
|
|
207
208
|
else if (TERMINAL_FAILURE_STATUSES.has(status)) {
|
|
208
|
-
const errMsg = ((_l = (_k = utx === null || utx === void 0 ? void 0 : utx.pcTx) === null || _k === void 0 ? void 0 : _k[0]) === null || _l === void 0 ? void 0 : _l.errorMsg)
|
|
209
|
-
|
|
209
|
+
const errMsg = ((_l = (_k = utx === null || utx === void 0 ? void 0 : utx.pcTx) === null || _k === void 0 ? void 0 : _k[0]) === null || _l === void 0 ? void 0 : _l.errorMsg)
|
|
210
|
+
? (0, formatters_1.normalizePcInsufficientFundsError)(utx.pcTx[0].errorMsg)
|
|
211
|
+
: `inbound terminated with status ${status}`;
|
|
210
212
|
progressHook === null || progressHook === void 0 ? void 0 : progressHook({
|
|
211
213
|
status: 'failed',
|
|
212
214
|
elapsedMs: elapsed(),
|
|
@@ -67,6 +67,7 @@ export declare function waitForAllOutboundTxsV2(ctx: OrchestratorContext, pushCh
|
|
|
67
67
|
initialWaitMs: number;
|
|
68
68
|
pollingIntervalMs: number;
|
|
69
69
|
timeout: number;
|
|
70
|
+
_resolvedSubTxId?: string;
|
|
70
71
|
progressHook?: (event: {
|
|
71
72
|
hopIndex: number;
|
|
72
73
|
route: TransactionRouteType;
|