@pushchain/core 5.1.4-alpha.9 → 5.1.5-alpha.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushchain/core",
3
- "version": "5.1.4-alpha.9",
3
+ "version": "5.1.5-alpha.0",
4
4
  "homepage": "https://push.org",
5
5
  "keywords": [
6
6
  "pushchain",
@@ -1,7 +1,7 @@
1
1
  import { PushChain } from './push-chain/push-chain';
2
2
  export type { ConversionQuote } from './constants/tokens';
3
3
  export type { UniversalSigner, UniversalAccount, UniversalSignerSkeleton, DerivedExecutorAccount, ResolvedAccount, ResolvedControllerAccounts, AccountType, AccountRole, } from './universal/universal.types';
4
- export type { ChainTarget, ChainSource, UniversalTo, TransactionRouteType, UniversalExecuteParams, UniversalOutboundTxRequest, PreparedUniversalTx, CascadedTxResponse, CascadeHopInfo, CascadeTrackOptions, CascadeProgressEvent, CascadeCompletionResult, MultiChainTxResponse, OutboundTxDetails, WaitForOutboundOptions, SvmGatewayAccountMeta, SvmExecutePayloadFields, SvmExecuteParams, AccountStatus, UEAStatus, RescueFundsParams, } from './orchestrator/orchestrator.types';
4
+ export type { ChainTarget, ChainSource, UniversalTo, TransactionRouteType, UniversalExecuteParams, UniversalOutboundTxRequest, PreparedUniversalTx, CascadedTxResponse, CascadeHopInfo, CascadeTrackOptions, CascadeProgressEvent, CascadeCompletionResult, MultiChainTxResponse, OutboundTxDetails, WaitForOutboundOptions, SvmGatewayAccountMeta, SvmExecutePayloadFields, AccountStatus, UEAStatus, RescueFundsParams, } from './orchestrator/orchestrator.types';
5
5
  export { parseUEAVersion } from './orchestrator/orchestrator.types';
6
6
  export { TransactionRoute, detectRoute, isChainTarget } from './orchestrator/route-detector';
7
7
  export { getCEAAddress, getPushAccountForCEA, isCEA, chainSupportsCEA, chainSupportsOutbound, getCEAFactoryAddress, getAllCEAAddresses, } from './orchestrator/cea-utils';
@@ -27,6 +27,7 @@ const payload_builder_1 = require("./payload-builder");
27
27
  const uea_manager_1 = require("./uea-manager");
28
28
  const gas_calculator_1 = require("./gas-calculator");
29
29
  const route_handlers_1 = require("./route-handlers");
30
+ const build_payload_1 = require("../svm-idl/build-payload");
30
31
  // ============================================================================
31
32
  // prepareTransaction
32
33
  // ============================================================================
@@ -110,18 +111,12 @@ function buildHopDescriptor(ctx, params, route, ueaAddress) {
110
111
  const targetChain = target.chain;
111
112
  // Branch: SVM vs EVM
112
113
  if ((0, payload_builders_1.isSvmChain)(targetChain)) {
113
- // SVM path: no CEA lookup, build SVM payload
114
- const hasSvmExecute = !!params.svmExecute;
115
- let svmPayload = '0x';
116
- if (hasSvmExecute) {
117
- const exec = params.svmExecute;
118
- svmPayload = (0, payload_builders_1.encodeSvmExecutePayload)({
119
- targetProgram: exec.targetProgram,
120
- accounts: exec.accounts,
121
- ixData: exec.ixData,
122
- instructionId: 2,
123
- });
124
- }
114
+ // SVM path: no CEA lookup, build SVM payload via IDL resolver
115
+ const { svmPayload, hasExecute: hasSvmExecute } = (0, build_payload_1.buildSvmPayloadFromParams)({
116
+ data: params.data,
117
+ to: target,
118
+ senderUea: ueaAddress,
119
+ });
125
120
  let prc20Token = selectors_1.ZERO_ADDRESS;
126
121
  let burnAmount = BigInt(0);
127
122
  if ((_b = params.funds) === null || _b === void 0 ? void 0 : _b.amount) {
@@ -432,7 +427,7 @@ function getSegmentType(route) {
432
427
  // composeCascade
433
428
  // ============================================================================
434
429
  function composeCascade(ctx, segments, ueaAddress, ueaBalance, ueaNonce) {
435
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
430
+ var _a, _b, _c, _d, _e, _f, _g;
436
431
  let accumulatedPushMulticalls = [];
437
432
  const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
438
433
  // Compute per-outbound nativeValueForGas from UEA balance
@@ -465,10 +460,9 @@ function composeCascade(ctx, segments, ueaAddress, ueaBalance, ueaNonce) {
465
460
  if (isSvmSegment) {
466
461
  // SVM: use the pre-built SVM payload from the hop descriptor
467
462
  outboundPayload = (_a = firstHop.svmPayload) !== null && _a !== void 0 ? _a : '0x';
468
- // For SVM, target is the recipient/program from the hop params
463
+ // For SVM, to.address IS the target (program for execute, recipient for withdraw)
469
464
  const svmTarget = firstHop.params.to;
470
- targetForOutbound =
471
- (_c = (_b = firstHop.params.svmExecute) === null || _b === void 0 ? void 0 : _b.targetProgram) !== null && _c !== void 0 ? _c : svmTarget.address;
465
+ targetForOutbound = svmTarget.address;
472
466
  }
473
467
  else if (isMigration) {
474
468
  // Migration: use raw 4-byte MIGRATION_SELECTOR, no multicall wrapping
@@ -482,7 +476,7 @@ function composeCascade(ctx, segments, ueaAddress, ueaBalance, ueaNonce) {
482
476
  targetForOutbound = (firstHop === null || firstHop === void 0 ? void 0 : firstHop.ceaAddress) || ueaAddress;
483
477
  }
484
478
  // Build outbound request
485
- const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetForOutbound, segment.prc20Token || selectors_1.ZERO_ADDRESS, segment.totalBurnAmount || BigInt(0), (_d = segment.gasLimit) !== null && _d !== void 0 ? _d : BigInt(0), outboundPayload, ueaAddress);
479
+ const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetForOutbound, segment.prc20Token || selectors_1.ZERO_ADDRESS, segment.totalBurnAmount || BigInt(0), (_b = segment.gasLimit) !== null && _b !== void 0 ? _b : BigInt(0), outboundPayload, ueaAddress);
486
480
  // Build approval + outbound multicalls
487
481
  const segGasFee = segment.gasFee || BigInt(0);
488
482
  const outboundMulticalls = (0, payload_builders_1.buildOutboundApprovalAndCall)({
@@ -507,7 +501,7 @@ function composeCascade(ctx, segments, ueaAddress, ueaBalance, ueaNonce) {
507
501
  // Build push multicalls from this hop's own data (e.g., counter.increment())
508
502
  // This is the Route 3 hop's payload that executes on Push Chain after inbound.
509
503
  const hop0 = segment.hops[0];
510
- if ((_e = hop0 === null || hop0 === void 0 ? void 0 : hop0.params) === null || _e === void 0 ? void 0 : _e.data) {
504
+ if ((_c = hop0 === null || hop0 === void 0 ? void 0 : hop0.params) === null || _c === void 0 ? void 0 : _c.data) {
511
505
  const hopPushMulticalls = (0, payload_builders_1.buildExecuteMulticall)({
512
506
  execute: {
513
507
  to: hop0.params.to,
@@ -543,7 +537,7 @@ function composeCascade(ctx, segments, ueaAddress, ueaBalance, ueaNonce) {
543
537
  let drainAmount = BigInt(0);
544
538
  let tokenMintHex;
545
539
  const params = hop.params;
546
- if (((_f = params.funds) === null || _f === void 0 ? void 0 : _f.amount) && params.funds.amount > BigInt(0)) {
540
+ if (((_d = params.funds) === null || _d === void 0 ? void 0 : _d.amount) && params.funds.amount > BigInt(0)) {
547
541
  drainAmount = params.funds.amount;
548
542
  const token = params.funds.token;
549
543
  if (token && token.address) {
@@ -572,7 +566,7 @@ function composeCascade(ctx, segments, ueaAddress, ueaBalance, ueaNonce) {
572
566
  });
573
567
  const svmBurnAmount = segment.totalBurnAmount || BigInt(0);
574
568
  const outboundReq = (0, payload_builders_1.buildOutboundRequest)(gatewayProgramHex, segment.prc20Token ||
575
- (0, helpers_1.getNativePRC20ForChain)(sourceChain, ctx.pushNetwork), svmBurnAmount, (_g = segment.gasLimit) !== null && _g !== void 0 ? _g : BigInt(0), svmPayload, ueaAddress);
569
+ (0, helpers_1.getNativePRC20ForChain)(sourceChain, ctx.pushNetwork), svmBurnAmount, (_e = segment.gasLimit) !== null && _e !== void 0 ? _e : BigInt(0), svmPayload, ueaAddress);
576
570
  const inboundGasFee = segment.gasFee || BigInt(0);
577
571
  const outboundMulticalls = (0, payload_builders_1.buildOutboundApprovalAndCall)({
578
572
  prc20Token: segment.prc20Token ||
@@ -598,7 +592,7 @@ function composeCascade(ctx, segments, ueaAddress, ueaBalance, ueaNonce) {
598
592
  let tokenAddress = selectors_1.ZERO_ADDRESS;
599
593
  let amount = BigInt(0);
600
594
  const params = hop.params;
601
- if ((_h = params.funds) === null || _h === void 0 ? void 0 : _h.amount) {
595
+ if ((_f = params.funds) === null || _f === void 0 ? void 0 : _f.amount) {
602
596
  const token = params.funds.token;
603
597
  if (token) {
604
598
  if (token.mechanism === 'native') {
@@ -645,7 +639,7 @@ function composeCascade(ctx, segments, ueaAddress, ueaBalance, ueaNonce) {
645
639
  // Wrap CEA multicall in outbound from Push Chain
646
640
  const ceaPayload = (0, payload_builders_1.buildCeaMulticallPayload)(ceaMulticalls);
647
641
  const outboundReq = (0, payload_builders_1.buildOutboundRequest)(ceaAddress, segment.prc20Token ||
648
- (0, helpers_1.getNativePRC20ForChain)(sourceChain, ctx.pushNetwork), segment.totalBurnAmount || BigInt(0), (_j = segment.gasLimit) !== null && _j !== void 0 ? _j : BigInt(0), ceaPayload, ueaAddress);
642
+ (0, helpers_1.getNativePRC20ForChain)(sourceChain, ctx.pushNetwork), segment.totalBurnAmount || BigInt(0), (_g = segment.gasLimit) !== null && _g !== void 0 ? _g : BigInt(0), ceaPayload, ueaAddress);
649
643
  const inboundGasFee = segment.gasFee || BigInt(0);
650
644
  const outboundMulticalls = (0, payload_builders_1.buildOutboundApprovalAndCall)({
651
645
  prc20Token: segment.prc20Token ||
@@ -74,15 +74,15 @@ function executeFundsWithPayload(ctx, execute, eventBuffer, getResponseCallbacks
74
74
  const ueaAddress = (0, uea_manager_1.computeUEAOffchain)(ctx);
75
75
  const ueaBalance = yield ctx.pushClient.getBalance(ueaAddress);
76
76
  (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_03_02, ueaAddress, deployed);
77
- // Determine USD to deposit via gateway (8 decimals) with caps: min=$1, max=$10
77
+ // Determine USD to deposit via gateway (8 decimals) with caps: min=$1, max=$1000
78
78
  const oneUsd = utils_1.Utils.helpers.parseUnits('1', 8);
79
- const tenUsd = utils_1.Utils.helpers.parseUnits('10', 8);
79
+ const maxUsd = utils_1.Utils.helpers.parseUnits('1000', 8);
80
80
  const deficit = requiredFunds > ueaBalance ? requiredFunds - ueaBalance : BigInt(0);
81
81
  let depositUsd = deficit > BigInt(0) ? ctx.pushClient.pushToUSDC(deficit) : oneUsd;
82
82
  if (depositUsd < oneUsd)
83
83
  depositUsd = oneUsd;
84
- if (depositUsd > tenUsd)
85
- throw new Error('Deposit value exceeds max $10 worth of native token');
84
+ if (depositUsd > maxUsd)
85
+ throw new Error('Deposit value exceeds max $1000 worth of native token');
86
86
  (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_02, depositUsd);
87
87
  // If SVM, clamp depositUsd to on-chain Config caps
88
88
  if (chain_1.CHAIN_INFO[chain].vm === enums_1.VM.SVM) {
@@ -28,6 +28,9 @@ const confirmation_1 = require("./confirmation");
28
28
  const gateway_client_1 = require("./gateway-client");
29
29
  const response_builder_1 = require("./response-builder");
30
30
  const push_chain_tx_1 = require("./push-chain-tx");
31
+ const gas_calculator_1 = require("./gas-calculator");
32
+ const helpers_2 = require("./helpers");
33
+ const price_fetch_1 = require("../../price-fetch/price-fetch");
31
34
  function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks) {
32
35
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
33
36
  var _a, _b;
@@ -197,8 +200,106 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
197
200
  const fundDifference = requiredFunds - funds;
198
201
  const fixedPushAmount = utils_1.Utils.helpers.parseUnits('0.001', 18);
199
202
  const lockAmount = funds < requiredFunds ? fundDifference : fixedPushAmount;
200
- const lockAmountInUSD = ctx.pushClient.pushToUSDC(lockAmount);
201
- const feeLockTxHashBytes = yield (0, gateway_client_1.lockFee)(ctx, lockAmountInUSD, universalPayload, req);
203
+ // Size the USD deposit against the REAL Uniswap pool rate (not the fixed
204
+ // $0.10/PC SDK rate) for EVM origins. The pool typically prices PC much
205
+ // higher than $0.10, so pushToUSDC under-provisions and the resulting
206
+ // deposit gets clamped up to the $1 minimum, producing near-zero WPC.
207
+ // When the quoted USD exceeds the $1000 cap the later clamp kicks in
208
+ // (pool limit surfaces via the pre-flight capacity message).
209
+ // Falls back to pushToUSDC if the quoter is unavailable.
210
+ const { vm: sizingOriginVm } = chain_1.CHAIN_INFO[chain];
211
+ let lockAmountInUSD = ctx.pushClient.pushToUSDC(lockAmount);
212
+ if (sizingOriginVm === enums_1.VM.EVM && lockAmount > BigInt(0)) {
213
+ // Target lockAmount × 1.2 so that the 10% slippage margin applied by
214
+ // the pre-flight check (safeUPC = predictedUPC × 0.9) leaves enough
215
+ // headroom even when Uniswap V3 exactOutput↔exactInput quotes aren't
216
+ // perfectly symmetric (tick-math rounding).
217
+ const targetWPC = (lockAmount * BigInt(12)) / BigInt(10);
218
+ const originPrc20ForSizing = (0, helpers_2.getNativePRC20ForChain)(chain, ctx.pushNetwork);
219
+ const requiredNative = yield (0, gas_calculator_1.estimateNativeForDesiredDeposit)(ctx, targetWPC, originPrc20ForSizing);
220
+ if (requiredNative > BigInt(0)) {
221
+ const ethPriceForSizing = yield new price_fetch_1.PriceFetch(ctx.rpcUrls).getPrice(chain);
222
+ if (ethPriceForSizing > BigInt(0)) {
223
+ // requiredNative (18-dec wei) × ethPrice (8-dec USD/ETH) / 1e18 = USD in 8-dec
224
+ const poolBasedUsd = (requiredNative * ethPriceForSizing) / BigInt(1e18);
225
+ (0, context_1.printLog)(ctx, `Fee-lock sizing: pushToUSDC=${lockAmountInUSD.toString()} (fixed $0.10/PC), ` +
226
+ `poolBased=${poolBasedUsd.toString()} (pool quote for ${targetWPC.toString()} WPC) — using poolBased`);
227
+ lockAmountInUSD = poolBasedUsd;
228
+ }
229
+ }
230
+ }
231
+ // Apply minimum deposit override (e.g., Route 2 needs enough UPC for outbound swap)
232
+ const effectiveLockAmountInUSD = execute._minimumDepositUsd && execute._minimumDepositUsd > lockAmountInUSD
233
+ ? execute._minimumDepositUsd
234
+ : lockAmountInUSD;
235
+ // Pre-flight: predict the actual $PC the UEA will receive after the
236
+ // on-chain pETH → WPC swap and validate it covers requiredFunds.
237
+ // Uses the same Uniswap V3 quoter the chain uses (execute_inbound_gas.go).
238
+ // Mirrors the pattern in route-handlers.ts (Route 2/3).
239
+ const { vm: originVm } = chain_1.CHAIN_INFO[chain];
240
+ if (originVm === enums_1.VM.EVM) {
241
+ try {
242
+ // Replicate lockFee's USD → native conversion (with its $1–$1000 clamp)
243
+ const oneUsd = utils_1.Utils.helpers.parseUnits('1', 8);
244
+ const maxUsd = utils_1.Utils.helpers.parseUnits('1000', 8);
245
+ let depositUsd = effectiveLockAmountInUSD < oneUsd ? oneUsd : effectiveLockAmountInUSD;
246
+ if (depositUsd > maxUsd)
247
+ depositUsd = maxUsd;
248
+ const ethPrice = yield new price_fetch_1.PriceFetch(ctx.rpcUrls).getPrice(chain);
249
+ if (ethPrice > BigInt(0)) {
250
+ const nativeAmountETH = (depositUsd * BigInt(1e18) + (ethPrice - BigInt(1))) / ethPrice + BigInt(1);
251
+ const originPrc20 = (0, helpers_2.getNativePRC20ForChain)(chain, ctx.pushNetwork);
252
+ const predictedUPC = yield (0, gas_calculator_1.estimateDepositFromLockedNative)(ctx, nativeAmountETH, originPrc20);
253
+ if (predictedUPC > BigInt(0)) {
254
+ // 10% slippage margin (same as route-handlers.ts)
255
+ const safeUPC = (predictedUPC * BigInt(90)) / BigInt(100);
256
+ const totalAvailable = safeUPC + funds;
257
+ (0, context_1.printLog)(ctx, `Fee-lock pre-flight: deposit ${depositUsd.toString()} USD → ` +
258
+ `~${nativeAmountETH.toString()} wei ETH → ~${predictedUPC.toString()} UPC ` +
259
+ `(safe: ${safeUPC.toString()}), existing: ${funds.toString()}, ` +
260
+ `total: ${totalAvailable.toString()}, required: ${requiredFunds.toString()}`);
261
+ if (totalAvailable < requiredFunds) {
262
+ const shortfall = requiredFunds - totalAvailable;
263
+ // On failure only: probe pool capacity at the max cap so the
264
+ // caller gets a readable "max transferable right now" number.
265
+ // One extra quoter call — not run on the success path.
266
+ let maxTransferableNote = '';
267
+ if (depositUsd < maxUsd) {
268
+ const maxNativeAmountETH = (maxUsd * BigInt(1e18) + (ethPrice - BigInt(1))) / ethPrice + BigInt(1);
269
+ const maxPredictedUPC = yield (0, gas_calculator_1.estimateDepositFromLockedNative)(ctx, maxNativeAmountETH, originPrc20);
270
+ if (maxPredictedUPC > BigInt(0)) {
271
+ const maxSafeUPC = (maxPredictedUPC * BigInt(90)) / BigInt(100);
272
+ const gasReserve = utils_1.Utils.helpers.parseUnits('0.01', 18);
273
+ const maxFromDeposit = maxSafeUPC > gasReserve ? maxSafeUPC - gasReserve : BigInt(0);
274
+ const maxTransferable = funds + maxFromDeposit;
275
+ maxTransferableNote =
276
+ `Max transferable right now (at $1000 cap, pool-limited): ` +
277
+ `~${(Number(maxTransferable) / 1e18).toFixed(4)} $PC ` +
278
+ `(UEA balance ${(Number(funds) / 1e18).toFixed(4)} + ` +
279
+ `pool-safe deposit ${(Number(maxFromDeposit) / 1e18).toFixed(4)} − gas).`;
280
+ (0, context_1.printLog)(ctx, `Fee-lock capacity: ${maxTransferableNote}`);
281
+ }
282
+ }
283
+ throw new Error(`Insufficient deposit: the fee-lock will deposit ~${(Number(safeUPC) / 1e18).toFixed(4)} $PC ` +
284
+ `but the transaction requires ~${(Number(requiredFunds) / 1e18).toFixed(4)} $PC ` +
285
+ `(shortfall: ~${(Number(shortfall) / 1e18).toFixed(4)} $PC). ` +
286
+ `The fee-lock deposit is capped at $1000 USD. ` +
287
+ (maxTransferableNote ? maxTransferableNote + ' ' : '') +
288
+ `Reduce the transfer value or pre-fund the UEA (${UEA}) on Push Chain.`);
289
+ }
290
+ }
291
+ }
292
+ }
293
+ catch (err) {
294
+ // If the error is our own insufficient-deposit error, rethrow it
295
+ if (err instanceof Error && err.message.startsWith('Insufficient deposit')) {
296
+ throw err;
297
+ }
298
+ // Otherwise quoter failed — log and continue (same fallback as route-handlers)
299
+ (0, context_1.printLog)(ctx, `Fee-lock pre-flight quote failed, proceeding without validation: ${err instanceof Error ? err.message : String(err)}`);
300
+ }
301
+ }
302
+ const feeLockTxHashBytes = yield (0, gateway_client_1.lockFee)(ctx, effectiveLockAmountInUSD, universalPayload, req);
202
303
  feeLockTxHash = (0, viem_1.bytesToHex)(feeLockTxHashBytes);
203
304
  verificationData = (0, viem_1.bytesToHex)(feeLockTxHashBytes);
204
305
  const { vm } = chain_1.CHAIN_INFO[chain];
@@ -36,3 +36,22 @@ export declare function calculateGasAmountFromAmountOutMinETH(ctx: OrchestratorC
36
36
  }) => Promise<ConversionQuote>): Promise<{
37
37
  gasAmount: bigint;
38
38
  }>;
39
+ /**
40
+ * Predicts how much UPC (WPC) the chain will deposit to the UEA from a given
41
+ * amount of locked native token (e.g., ETH on Sepolia). The chain converts
42
+ * locked ETH → pETH (PRC-20) → WPC via Uniswap V3 swap on Push Chain.
43
+ *
44
+ * Queries the same Uniswap V3 QuoterV2 the chain uses in execute_inbound_gas.go.
45
+ * Returns 0 on any failure (caller should fall back to other logic).
46
+ */
47
+ export declare function estimateDepositFromLockedNative(ctx: OrchestratorContext, nativeAmountForLocker: bigint, prc20Token: `0x${string}`): Promise<bigint>;
48
+ /**
49
+ * Inverse of estimateDepositFromLockedNative: given a desired WPC output,
50
+ * asks the Push Chain Uniswap V3 pool how much native PRC-20 (pETH) input is
51
+ * required to produce exactly that output via QuoterV2.quoteExactOutputSingle.
52
+ *
53
+ * Used to size fee-lock deposits against the real on-chain pool rate instead
54
+ * of the fixed $0.10/PC SDK rate. Returns 0 on any failure (caller should
55
+ * fall back to the fixed-rate sizing).
56
+ */
57
+ export declare function estimateNativeForDesiredDeposit(ctx: OrchestratorContext, desiredWpc: bigint, prc20Token: `0x${string}`): Promise<bigint>;
@@ -10,6 +10,8 @@ exports.estimateNativeValueForSwap = estimateNativeValueForSwap;
10
10
  exports.queryRescueGasFee = queryRescueGasFee;
11
11
  exports.calculateNativeAmountForDeposit = calculateNativeAmountForDeposit;
12
12
  exports.calculateGasAmountFromAmountOutMinETH = calculateGasAmountFromAmountOutMinETH;
13
+ exports.estimateDepositFromLockedNative = estimateDepositFromLockedNative;
14
+ exports.estimateNativeForDesiredDeposit = estimateNativeForDesiredDeposit;
13
15
  const tslib_1 = require("tslib");
14
16
  const web3_js_1 = require("@solana/web3.js");
15
17
  const viem_1 = require("viem");
@@ -335,13 +337,13 @@ function calculateNativeAmountForDeposit(ctx, chain, requiredFunds, ueaBalance)
335
337
  var _a, _b;
336
338
  (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_01);
337
339
  const oneUsd = utils_1.Utils.helpers.parseUnits('1', 8);
338
- const tenUsd = utils_1.Utils.helpers.parseUnits('10', 8);
340
+ const maxUsd = utils_1.Utils.helpers.parseUnits('1000', 8);
339
341
  const deficit = requiredFunds > ueaBalance ? requiredFunds - ueaBalance : BigInt(0);
340
342
  let depositUsd = deficit > BigInt(0) ? ctx.pushClient.pushToUSDC(deficit) : oneUsd;
341
343
  if (depositUsd < oneUsd)
342
344
  depositUsd = oneUsd;
343
- if (depositUsd > tenUsd)
344
- throw new Error('Deposit value exceeds max $10 worth of native token');
345
+ if (depositUsd > maxUsd)
346
+ throw new Error('Deposit value exceeds max $1000 worth of native token');
345
347
  if (chain_1.CHAIN_INFO[chain].vm === enums_1.VM.SVM) {
346
348
  const svmClient = new svm_client_1.SvmClient({
347
349
  rpcUrls: ctx.rpcUrls[enums_1.CHAIN.SOLANA_DEVNET] ||
@@ -421,4 +423,188 @@ function calculateGasAmountFromAmountOutMinETH(ctx, gasTokenAddress, amountOutMi
421
423
  return { gasAmount };
422
424
  });
423
425
  }
426
+ // ============================================================================
427
+ // Estimate UPC deposit from locked ETH via Uniswap V3 quote
428
+ // ============================================================================
429
+ /**
430
+ * Predicts how much UPC (WPC) the chain will deposit to the UEA from a given
431
+ * amount of locked native token (e.g., ETH on Sepolia). The chain converts
432
+ * locked ETH → pETH (PRC-20) → WPC via Uniswap V3 swap on Push Chain.
433
+ *
434
+ * Queries the same Uniswap V3 QuoterV2 the chain uses in execute_inbound_gas.go.
435
+ * Returns 0 on any failure (caller should fall back to other logic).
436
+ */
437
+ function estimateDepositFromLockedNative(ctx, nativeAmountForLocker, prc20Token) {
438
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
439
+ var _a, _b;
440
+ try {
441
+ const pushChain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
442
+ 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;
443
+ if (!quoterAddress || quoterAddress.startsWith('0xTBD'))
444
+ return BigInt(0);
445
+ // Get UniversalCore → WPC address + fee tier (reuses existing ABI)
446
+ const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
447
+ const universalCoreAddress = yield ctx.pushClient.readContract({
448
+ address: gatewayPcAddress,
449
+ abi: abi_1.UNIVERSAL_GATEWAY_PC,
450
+ functionName: 'UNIVERSAL_CORE',
451
+ args: [],
452
+ });
453
+ const [wpcAddress, feeTier] = yield Promise.all([
454
+ ctx.pushClient.readContract({
455
+ address: universalCoreAddress,
456
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
457
+ functionName: 'WPC',
458
+ args: [],
459
+ }),
460
+ ctx.pushClient.readContract({
461
+ address: universalCoreAddress,
462
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
463
+ functionName: 'defaultFeeTier',
464
+ args: [prc20Token],
465
+ }),
466
+ ]);
467
+ if (!feeTier || !wpcAddress)
468
+ return BigInt(0);
469
+ // QuoterV2.quoteExactInputSingle — same call the chain relay makes
470
+ const QUOTER_ABI = [
471
+ {
472
+ type: 'function',
473
+ name: 'quoteExactInputSingle',
474
+ inputs: [
475
+ {
476
+ type: 'tuple',
477
+ components: [
478
+ { name: 'tokenIn', type: 'address' },
479
+ { name: 'tokenOut', type: 'address' },
480
+ { name: 'amountIn', type: 'uint256' },
481
+ { name: 'fee', type: 'uint24' },
482
+ { name: 'sqrtPriceLimitX96', type: 'uint160' },
483
+ ],
484
+ },
485
+ ],
486
+ outputs: [
487
+ { name: 'amountOut', type: 'uint256' },
488
+ { name: 'sqrtPriceX96After', type: 'uint160' },
489
+ { name: 'initializedTicksCrossed', type: 'uint32' },
490
+ { name: 'gasEstimate', type: 'uint256' },
491
+ ],
492
+ stateMutability: 'view',
493
+ },
494
+ ];
495
+ const result = yield ctx.pushClient.readContract({
496
+ address: quoterAddress,
497
+ abi: QUOTER_ABI,
498
+ functionName: 'quoteExactInputSingle',
499
+ args: [
500
+ {
501
+ tokenIn: prc20Token,
502
+ tokenOut: wpcAddress,
503
+ amountIn: nativeAmountForLocker,
504
+ fee: feeTier,
505
+ sqrtPriceLimitX96: BigInt(0),
506
+ },
507
+ ],
508
+ });
509
+ const amountOut = result[0];
510
+ (0, context_1.printLog)(ctx, `estimateDepositFromLockedNative — quote: ${nativeAmountForLocker.toString()} pETH → ${amountOut.toString()} WPC (fee tier: ${feeTier})`);
511
+ return amountOut;
512
+ }
513
+ catch (err) {
514
+ (0, context_1.printLog)(ctx, `estimateDepositFromLockedNative — failed: ${err instanceof Error ? err.message : String(err)}`);
515
+ return BigInt(0);
516
+ }
517
+ });
518
+ }
519
+ /**
520
+ * Inverse of estimateDepositFromLockedNative: given a desired WPC output,
521
+ * asks the Push Chain Uniswap V3 pool how much native PRC-20 (pETH) input is
522
+ * required to produce exactly that output via QuoterV2.quoteExactOutputSingle.
523
+ *
524
+ * Used to size fee-lock deposits against the real on-chain pool rate instead
525
+ * of the fixed $0.10/PC SDK rate. Returns 0 on any failure (caller should
526
+ * fall back to the fixed-rate sizing).
527
+ */
528
+ function estimateNativeForDesiredDeposit(ctx, desiredWpc, prc20Token) {
529
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
530
+ var _a, _b;
531
+ try {
532
+ if (desiredWpc <= BigInt(0))
533
+ return BigInt(0);
534
+ const pushChain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
535
+ 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;
536
+ if (!quoterAddress || quoterAddress.startsWith('0xTBD'))
537
+ return BigInt(0);
538
+ const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
539
+ const universalCoreAddress = yield ctx.pushClient.readContract({
540
+ address: gatewayPcAddress,
541
+ abi: abi_1.UNIVERSAL_GATEWAY_PC,
542
+ functionName: 'UNIVERSAL_CORE',
543
+ args: [],
544
+ });
545
+ const [wpcAddress, feeTier] = yield Promise.all([
546
+ ctx.pushClient.readContract({
547
+ address: universalCoreAddress,
548
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
549
+ functionName: 'WPC',
550
+ args: [],
551
+ }),
552
+ ctx.pushClient.readContract({
553
+ address: universalCoreAddress,
554
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
555
+ functionName: 'defaultFeeTier',
556
+ args: [prc20Token],
557
+ }),
558
+ ]);
559
+ if (!feeTier || !wpcAddress)
560
+ return BigInt(0);
561
+ const QUOTER_ABI = [
562
+ {
563
+ type: 'function',
564
+ name: 'quoteExactOutputSingle',
565
+ inputs: [
566
+ {
567
+ type: 'tuple',
568
+ components: [
569
+ { name: 'tokenIn', type: 'address' },
570
+ { name: 'tokenOut', type: 'address' },
571
+ { name: 'amount', type: 'uint256' },
572
+ { name: 'fee', type: 'uint24' },
573
+ { name: 'sqrtPriceLimitX96', type: 'uint160' },
574
+ ],
575
+ },
576
+ ],
577
+ outputs: [
578
+ { name: 'amountIn', type: 'uint256' },
579
+ { name: 'sqrtPriceX96After', type: 'uint160' },
580
+ { name: 'initializedTicksCrossed', type: 'uint32' },
581
+ { name: 'gasEstimate', type: 'uint256' },
582
+ ],
583
+ stateMutability: 'view',
584
+ },
585
+ ];
586
+ const result = yield ctx.pushClient.readContract({
587
+ address: quoterAddress,
588
+ abi: QUOTER_ABI,
589
+ functionName: 'quoteExactOutputSingle',
590
+ args: [
591
+ {
592
+ tokenIn: prc20Token,
593
+ tokenOut: wpcAddress,
594
+ amount: desiredWpc,
595
+ fee: feeTier,
596
+ sqrtPriceLimitX96: BigInt(0),
597
+ },
598
+ ],
599
+ });
600
+ const amountIn = result[0];
601
+ (0, context_1.printLog)(ctx, `estimateNativeForDesiredDeposit — quote: ${desiredWpc.toString()} WPC ← ${amountIn.toString()} pETH (fee tier: ${feeTier})`);
602
+ return amountIn;
603
+ }
604
+ catch (err) {
605
+ (0, context_1.printLog)(ctx, `estimateNativeForDesiredDeposit — failed: ${err instanceof Error ? err.message : String(err)}`);
606
+ return BigInt(0);
607
+ }
608
+ });
609
+ }
424
610
  //# sourceMappingURL=gas-calculator.js.map
@@ -96,10 +96,10 @@ req) {
96
96
  const nativeTokenUsdPrice = yield new price_fetch_1.PriceFetch(ctx.rpcUrls).getPrice(chain);
97
97
  const nativeDecimals = 18;
98
98
  const oneUsd = utils_1.Utils.helpers.parseUnits('1', 8);
99
- const tenUsd = utils_1.Utils.helpers.parseUnits('10', 8);
99
+ const maxUsd = utils_1.Utils.helpers.parseUnits('1000', 8);
100
100
  let depositUsd = amount < oneUsd ? oneUsd : amount;
101
- if (depositUsd > tenUsd)
102
- depositUsd = tenUsd;
101
+ if (depositUsd > maxUsd)
102
+ depositUsd = maxUsd;
103
103
  let nativeAmount = (depositUsd * BigInt(Math.pow(10, nativeDecimals)) +
104
104
  (nativeTokenUsdPrice - BigInt(1))) /
105
105
  nativeTokenUsdPrice;
@@ -114,10 +114,10 @@ req) {
114
114
  ]);
115
115
  const nativeDecimals = 9;
116
116
  const oneUsd = utils_1.Utils.helpers.parseUnits('1', 8);
117
- const tenUsd = utils_1.Utils.helpers.parseUnits('10', 8);
117
+ const maxUsd = utils_1.Utils.helpers.parseUnits('1000', 8);
118
118
  let depositUsd = amount < oneUsd ? oneUsd : amount;
119
- if (depositUsd > tenUsd)
120
- depositUsd = tenUsd;
119
+ if (depositUsd > maxUsd)
120
+ depositUsd = maxUsd;
121
121
  let nativeAmount = (depositUsd * BigInt(Math.pow(10, nativeDecimals)) +
122
122
  (nativeTokenUsdPrice - BigInt(1))) /
123
123
  nativeTokenUsdPrice;
@@ -195,10 +195,24 @@ function extractPcTxAndTransform(ctx, pushChainUniversalTx, gatewayTxHash, event
195
195
  const lastPcTransaction = pushChainUniversalTx.pcTx.at(-1);
196
196
  (0, context_1.printLog)(ctx, `${label} — pcTx: ` + JSON.stringify(pushChainUniversalTx.pcTx.map((p) => ({ txHash: p.txHash, status: p.status, errorMsg: p.errorMsg })), null, 2));
197
197
  (0, context_1.printLog)(ctx, `${label} — using lastPcTransaction: ` + JSON.stringify(lastPcTransaction, null, 2));
198
- if (!(lastPcTransaction === null || lastPcTransaction === void 0 ? void 0 : lastPcTransaction.txHash)) {
199
- const failedPcTx = pushChainUniversalTx.pcTx.find((pcTx) => pcTx.status === 'FAILED' && pcTx.errorMsg);
198
+ if (!(lastPcTransaction === null || lastPcTransaction === void 0 ? void 0 : lastPcTransaction.txHash) || lastPcTransaction.status === 'FAILED') {
199
+ const failedPcTx = (lastPcTransaction === null || lastPcTransaction === void 0 ? void 0 : lastPcTransaction.status) === 'FAILED'
200
+ ? lastPcTransaction
201
+ : pushChainUniversalTx.pcTx.find((pcTx) => pcTx.status === 'FAILED' && pcTx.errorMsg);
200
202
  const errorDetails = (failedPcTx === null || failedPcTx === void 0 ? void 0 : failedPcTx.errorMsg) ? `: ${failedPcTx.errorMsg}` : '';
201
- throw new Error(`No transaction hash found in Push Chain response for gateway tx: ${gatewayTxHash}${errorDetails}`);
203
+ // Parse known UEA error selectors for actionable hints
204
+ let hint = '';
205
+ if (failedPcTx === null || failedPcTx === void 0 ? void 0 : failedPcTx.errorMsg) {
206
+ if (failedPcTx.errorMsg.includes('0xacfdb444')) {
207
+ hint = ' [ExecutionFailed: the subcall to the target contract reverted. ' +
208
+ 'Check that the target address can receive native tokens (has receive/fallback) ' +
209
+ 'and that calldata matches a valid function signature.]';
210
+ }
211
+ else if (failedPcTx.errorMsg.includes('0x179a867c')) {
212
+ hint = ' [ExpiredDeadline: the transaction deadline has passed.]';
213
+ }
214
+ }
215
+ throw new Error(`Push Chain transaction failed for gateway tx: ${gatewayTxHash}${errorDetails}${hint}`);
202
216
  }
203
217
  const tx = yield ctx.pushClient.getTransaction(lastPcTransaction.txHash);
204
218
  return transformFn(tx, eventBuffer);
@@ -150,7 +150,7 @@ function trackTransaction(ctx, txHash, options, callbacks) {
150
150
  throw new Error('trackTransaction requires ResponseBuilderCallbacks');
151
151
  }
152
152
  const { chain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork), progressHook, waitForCompletion = true, advanced = {}, } = options !== null && options !== void 0 ? options : {};
153
- const { timeout = 300000, rpcUrls = {} } = advanced;
153
+ const { timeout = 300000, pollingIntervalMs = 1000, rpcUrls = {} } = advanced;
154
154
  // Event buffer for replay via response.progressHook()
155
155
  const eventBuffer = [];
156
156
  // Helper to emit progress events
@@ -190,7 +190,7 @@ function trackTransaction(ctx, txHash, options, callbacks) {
190
190
  throw new Error(`Timeout: transaction ${txHash} not confirmed within ${timeout}ms`);
191
191
  }
192
192
  // Brief delay before retry
193
- yield new Promise((r) => setTimeout(r, 1000));
193
+ yield new Promise((r) => setTimeout(r, pollingIntervalMs));
194
194
  }
195
195
  }
196
196
  // Try to get UniversalTx data for richer progress reconstruction
@@ -256,7 +256,7 @@ function trackTransaction(ctx, txHash, options, callbacks) {
256
256
  function transformToUniversalTxResponse(ctx_1, tx_1) {
257
257
  return tslib_1.__awaiter(this, arguments, void 0, function* (ctx, tx, eventBuffer = [], callbacks) {
258
258
  const chain = ctx.universalSigner.account.chain;
259
- const { vm, chainId } = chain_1.CHAIN_INFO[chain];
259
+ let { vm, chainId } = chain_1.CHAIN_INFO[chain];
260
260
  let from;
261
261
  let to;
262
262
  let value;
@@ -269,6 +269,13 @@ function transformToUniversalTxResponse(ctx_1, tx_1) {
269
269
  throw new Error('UEA origin account is null');
270
270
  }
271
271
  originAddress = ueaOrigin.account.address;
272
+ // Use the resolved origin chain for vm/chainId so that the `origin`
273
+ // field reflects the transaction's actual origin, not the tracker's.
274
+ const resolvedChainInfo = chain_1.CHAIN_INFO[ueaOrigin.account.chain];
275
+ if (resolvedChainInfo) {
276
+ vm = resolvedChainInfo.vm;
277
+ chainId = resolvedChainInfo.chainId;
278
+ }
272
279
  from = (0, viem_1.getAddress)(tx.to);
273
280
  let decoded;
274
281
  if (tx.input !== '0x') {