@pushchain/core 5.1.4-alpha.0 → 5.1.4-alpha.10

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.
Files changed (108) hide show
  1. package/package.json +7 -8
  2. package/src/lib/constants/abi/factoryV1.d.ts +59 -76
  3. package/src/lib/constants/abi/factoryV1.js +0 -517
  4. package/src/lib/constants/abi/feeLocker.evm.d.ts +15 -50
  5. package/src/lib/constants/abi/feeLocker.evm.js +0 -385
  6. package/src/lib/constants/abi/index.d.ts +1 -1
  7. package/src/lib/constants/abi/index.js +1 -2
  8. package/src/lib/constants/abi/prc20.evm.d.ts +0 -53
  9. package/src/lib/constants/abi/prc20.evm.js +1 -42
  10. package/src/lib/constants/abi/uea.svm.d.ts +21 -99
  11. package/src/lib/constants/abi/uea.svm.js +0 -299
  12. package/src/lib/constants/abi/universalGatewayV0.evm.d.ts +45 -104
  13. package/src/lib/constants/abi/universalGatewayV0.evm.js +0 -2149
  14. package/src/lib/index.d.ts +1 -1
  15. package/src/lib/orchestrator/internals/cascade.d.ts +4 -2
  16. package/src/lib/orchestrator/internals/cascade.js +34 -18
  17. package/src/lib/orchestrator/internals/execute-standard.js +5 -1
  18. package/src/lib/orchestrator/internals/gas-calculator.d.ts +17 -0
  19. package/src/lib/orchestrator/internals/gas-calculator.js +236 -1
  20. package/src/lib/orchestrator/internals/push-chain-tx.js +24 -1
  21. package/src/lib/orchestrator/internals/route-handlers.js +60 -62
  22. package/src/lib/orchestrator/orchestrator.d.ts +5 -3
  23. package/src/lib/orchestrator/orchestrator.js +2 -12
  24. package/src/lib/orchestrator/orchestrator.types.d.ts +8 -15
  25. package/src/lib/progress-hook/progress-hook.js +1 -1
  26. package/src/lib/push-chain/push-chain.d.ts +5 -6
  27. package/src/lib/push-chain/push-chain.js +4 -3
  28. package/src/lib/universal/account/account.d.ts +16 -8
  29. package/src/lib/universal/account/account.js +118 -73
  30. package/src/lib/universal/signer/signer.js +1 -1
  31. package/src/lib/universal/universal.types.d.ts +2 -2
  32. package/src/index.js.map +0 -1
  33. package/src/lib/cache/cache.js.map +0 -1
  34. package/src/lib/constants/abi/cea.evm.js.map +0 -1
  35. package/src/lib/constants/abi/ceaFactory.evm.js.map +0 -1
  36. package/src/lib/constants/abi/erc20.evm.js.map +0 -1
  37. package/src/lib/constants/abi/factoryV1.js.map +0 -1
  38. package/src/lib/constants/abi/feeLocker.evm.js.map +0 -1
  39. package/src/lib/constants/abi/index.js.map +0 -1
  40. package/src/lib/constants/abi/prc20.evm.js.map +0 -1
  41. package/src/lib/constants/abi/uea-factory.js.map +0 -1
  42. package/src/lib/constants/abi/uea.evm.js.map +0 -1
  43. package/src/lib/constants/abi/uea.svm.js.map +0 -1
  44. package/src/lib/constants/abi/universalGateway.evm.js.map +0 -1
  45. package/src/lib/constants/abi/universalGatewayPC.evm.js.map +0 -1
  46. package/src/lib/constants/abi/universalGatewayV0.evm.js.map +0 -1
  47. package/src/lib/constants/chain.js.map +0 -1
  48. package/src/lib/constants/enums.js.map +0 -1
  49. package/src/lib/constants/index.js.map +0 -1
  50. package/src/lib/constants/selectors.js.map +0 -1
  51. package/src/lib/constants/tokens.js.map +0 -1
  52. package/src/lib/generated/uexecutor/v1/query.js.map +0 -1
  53. package/src/lib/generated/uexecutor/v1/types.js.map +0 -1
  54. package/src/lib/generated/uexecutor/v2/index.js.map +0 -1
  55. package/src/lib/generated/uexecutor/v2/query.js.map +0 -1
  56. package/src/lib/generated/uexecutor/v2/types.js.map +0 -1
  57. package/src/lib/generated/v1/tx.js.map +0 -1
  58. package/src/lib/index.js.map +0 -1
  59. package/src/lib/internal/bs58.js.map +0 -1
  60. package/src/lib/internal/buffer.js.map +0 -1
  61. package/src/lib/internal/global-buffer-polyfill.js.map +0 -1
  62. package/src/lib/orchestrator/cea-utils.js.map +0 -1
  63. package/src/lib/orchestrator/internals/account-manager.js.map +0 -1
  64. package/src/lib/orchestrator/internals/cascade.js.map +0 -1
  65. package/src/lib/orchestrator/internals/confirmation.js.map +0 -1
  66. package/src/lib/orchestrator/internals/context.js.map +0 -1
  67. package/src/lib/orchestrator/internals/execute-funds-only.js.map +0 -1
  68. package/src/lib/orchestrator/internals/execute-funds-payload.js.map +0 -1
  69. package/src/lib/orchestrator/internals/execute-standard.js.map +0 -1
  70. package/src/lib/orchestrator/internals/gas-calculator.js.map +0 -1
  71. package/src/lib/orchestrator/internals/gateway-client.js.map +0 -1
  72. package/src/lib/orchestrator/internals/helpers.js.map +0 -1
  73. package/src/lib/orchestrator/internals/index.js.map +0 -1
  74. package/src/lib/orchestrator/internals/outbound-sync.js.map +0 -1
  75. package/src/lib/orchestrator/internals/outbound-tracker.js.map +0 -1
  76. package/src/lib/orchestrator/internals/payload-builder.js.map +0 -1
  77. package/src/lib/orchestrator/internals/push-chain-tx.js.map +0 -1
  78. package/src/lib/orchestrator/internals/quote.js.map +0 -1
  79. package/src/lib/orchestrator/internals/rescue.js.map +0 -1
  80. package/src/lib/orchestrator/internals/response-builder.js.map +0 -1
  81. package/src/lib/orchestrator/internals/route-handlers.js.map +0 -1
  82. package/src/lib/orchestrator/internals/signing.js.map +0 -1
  83. package/src/lib/orchestrator/internals/svm-bridge.js.map +0 -1
  84. package/src/lib/orchestrator/internals/svm-helpers.js.map +0 -1
  85. package/src/lib/orchestrator/internals/tx-transformer.js.map +0 -1
  86. package/src/lib/orchestrator/internals/uea-manager.js.map +0 -1
  87. package/src/lib/orchestrator/orchestrator.js.map +0 -1
  88. package/src/lib/orchestrator/orchestrator.types.js.map +0 -1
  89. package/src/lib/orchestrator/payload-builders.js.map +0 -1
  90. package/src/lib/orchestrator/route-detector.js.map +0 -1
  91. package/src/lib/price-fetch/price-fetch.js.map +0 -1
  92. package/src/lib/progress-hook/progress-hook.js.map +0 -1
  93. package/src/lib/progress-hook/progress-hook.types.js.map +0 -1
  94. package/src/lib/push-chain/helpers/abis.js.map +0 -1
  95. package/src/lib/push-chain/helpers/addresses.js.map +0 -1
  96. package/src/lib/push-chain/push-chain.js.map +0 -1
  97. package/src/lib/push-client/push-client.js.map +0 -1
  98. package/src/lib/push-client/push-client.types.js.map +0 -1
  99. package/src/lib/universal/account/account.js.map +0 -1
  100. package/src/lib/universal/account/index.js.map +0 -1
  101. package/src/lib/universal/signer/index.js.map +0 -1
  102. package/src/lib/universal/signer/signer.js.map +0 -1
  103. package/src/lib/universal/signer/signer.types.js.map +0 -1
  104. package/src/lib/universal/universal.types.js.map +0 -1
  105. package/src/lib/utils.js.map +0 -1
  106. package/src/lib/vm-client/evm-client.js.map +0 -1
  107. package/src/lib/vm-client/svm-client.js.map +0 -1
  108. package/src/lib/vm-client/vm-client.types.js.map +0 -1
@@ -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, CascadedTransactionBuilder, 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, SvmExecuteParams, 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';
@@ -5,7 +5,7 @@
5
5
  * getSegmentType, composeCascade, createCascadedBuilder, createChainedBuilder.
6
6
  */
7
7
  import { TransactionRoute } from '../route-detector';
8
- import type { HopDescriptor, CascadeSegment, CascadeSegmentType, PreparedUniversalTx, CascadedTransactionBuilder, CascadeHopInfo, UniversalTxResponse, UniversalExecuteParams, MultiCall, WaitForOutboundOptions, OutboundTxDetails } from '../orchestrator.types';
8
+ import type { HopDescriptor, CascadeSegment, CascadeSegmentType, PreparedUniversalTx, CascadedTxResponse, CascadeHopInfo, UniversalTxResponse, UniversalExecuteParams, MultiCall, WaitForOutboundOptions, OutboundTxDetails } from '../orchestrator.types';
9
9
  import type { OrchestratorContext } from './context';
10
10
  export interface CascadeCallbacks {
11
11
  executeFn: (params: any) => Promise<UniversalTxResponse>;
@@ -20,4 +20,6 @@ export declare function buildHopDescriptor(ctx: OrchestratorContext, params: Uni
20
20
  export declare function classifyIntoSegments(hops: HopDescriptor[]): CascadeSegment[];
21
21
  export declare function getSegmentType(route: string): CascadeSegmentType;
22
22
  export declare function composeCascade(ctx: OrchestratorContext, segments: CascadeSegment[], ueaAddress: `0x${string}`, ueaBalance?: bigint, ueaNonce?: bigint): MultiCall[];
23
- export declare function createCascadedBuilder(ctx: OrchestratorContext, preparedTxs: PreparedUniversalTx[], callbacks: CascadeCallbacks): CascadedTransactionBuilder;
23
+ export declare function createCascadedBuilder(ctx: OrchestratorContext, preparedTxs: PreparedUniversalTx[], callbacks: CascadeCallbacks): {
24
+ send: () => Promise<CascadedTxResponse>;
25
+ };
@@ -37,16 +37,28 @@ function prepareTransaction(ctx, params, callbacks) {
37
37
  clientChain: ctx.universalSigner.account.chain,
38
38
  });
39
39
  const route = (0, route_detector_1.detectRoute)(params);
40
- // Skip getCode if accountStatusCache already confirmed deployment
40
+ // Push native EOA: block Route 1 — use sendTransaction() for direct Push calls
41
+ const signerChain = ctx.universalSigner.account.chain;
42
+ const isPushNativeEOA = (0, helpers_1.isPushChain)(signerChain);
43
+ if (isPushNativeEOA && route === route_detector_1.TransactionRoute.UOA_TO_PUSH) {
44
+ throw new Error('Push native accounts cannot use prepareTransaction for Push Chain transactions. ' +
45
+ 'Use sendTransaction() instead for direct Push Chain calls.');
46
+ }
47
+ // Fetch UEA nonce (skip for Push native EOA — uses EVM nonce, not UEA contract nonce)
41
48
  let nonce;
42
- const deployedHintCascade = (_b = (_a = ctx.accountStatusCache) === null || _a === void 0 ? void 0 : _a.uea) === null || _b === void 0 ? void 0 : _b.deployed;
43
49
  const ueaAddress = (0, uea_manager_1.computeUEAOffchain)(ctx);
44
- if (deployedHintCascade) {
45
- nonce = yield (0, uea_manager_1.getUEANonce)(ctx, ueaAddress);
50
+ if (isPushNativeEOA) {
51
+ nonce = BigInt(0);
46
52
  }
47
53
  else {
48
- const status = yield (0, uea_manager_1.getUeaStatusAndNonce)(ctx);
49
- nonce = status.nonce;
54
+ const deployedHintCascade = (_b = (_a = ctx.accountStatusCache) === null || _a === void 0 ? void 0 : _a.uea) === null || _b === void 0 ? void 0 : _b.deployed;
55
+ if (deployedHintCascade) {
56
+ nonce = yield (0, uea_manager_1.getUEANonce)(ctx, ueaAddress);
57
+ }
58
+ else {
59
+ const status = yield (0, uea_manager_1.getUeaStatusAndNonce)(ctx);
60
+ nonce = status.nonce;
61
+ }
50
62
  }
51
63
  // Build the payload based on route
52
64
  const { payload, gatewayRequest } = yield (0, route_handlers_1.buildPayloadForRoute)(ctx, params, route, nonce);
@@ -62,8 +74,6 @@ function prepareTransaction(ctx, params, callbacks) {
62
74
  nonce,
63
75
  deadline,
64
76
  _hop: hop,
65
- thenOn: (nextTx) => createCascadedBuilder(ctx, [prepared, nextTx], callbacks),
66
- send: () => callbacks.executeFn(params),
67
77
  };
68
78
  return prepared;
69
79
  });
@@ -222,8 +232,13 @@ function buildHopDescriptor(ctx, params, route, ueaAddress) {
222
232
  burnAmount = params.value;
223
233
  }
224
234
  else if (params.data) {
235
+ // PAYLOAD-only (no value transfer): still need native PRC-20 token for
236
+ // chain namespace lookup + gas fees, but burn amount must be zero.
237
+ // Matches the direct executeUoaToCea path (route-handlers.ts).
238
+ // Using burnAmount=1 would trigger transferFrom on the PRC-20 token,
239
+ // which reverts when the UEA has no PRC-20 balance for that chain.
225
240
  prc20Token = (0, helpers_1.getNativePRC20ForChain)(targetChain, ctx.pushNetwork);
226
- burnAmount = BigInt(1); // Minimum for precompile
241
+ burnAmount = BigInt(0);
227
242
  }
228
243
  // Query gas fee
229
244
  let gasToken = selectors_1.ZERO_ADDRESS;
@@ -285,10 +300,12 @@ function buildHopDescriptor(ctx, params, route, ueaAddress) {
285
300
  gasToken = result.gasToken;
286
301
  gasFee = result.gasFee;
287
302
  }
288
- return Object.assign(Object.assign({}, baseDescriptor), { sourceChain, ceaAddress: ceaPdaHex, isSvmTarget: true, prc20Token, burnAmount: amount > BigInt(0) ? amount : BigInt(1), gasToken,
303
+ return Object.assign(Object.assign({}, baseDescriptor), { sourceChain, ceaAddress: ceaPdaHex, isSvmTarget: true, prc20Token, burnAmount: amount, gasToken,
289
304
  gasFee });
290
305
  }
291
- const { cea: ceaAddress, isDeployed } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, sourceChain, (_h = ctx.rpcUrls[sourceChain]) === null || _h === void 0 ? void 0 : _h[0]);
306
+ const { cea: ceaAddress } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, sourceChain, (_h = ctx.rpcUrls[sourceChain]) === null || _h === void 0 ? void 0 : _h[0]);
307
+ // CEA auto-deploys on-chain: Vault.finalizeUniversalTx calls CEAFactory.deployCEA()
308
+ // if CEA doesn't exist yet. No SDK-side blocking needed.
292
309
  // Determine token/amount for the inbound
293
310
  let tokenAddress = selectors_1.ZERO_ADDRESS;
294
311
  let amount = BigInt(0);
@@ -321,7 +338,7 @@ function buildHopDescriptor(ctx, params, route, ueaAddress) {
321
338
  }
322
339
  return Object.assign(Object.assign({}, baseDescriptor), { sourceChain,
323
340
  ceaAddress,
324
- prc20Token, burnAmount: amount > BigInt(0) ? amount : BigInt(1), gasToken,
341
+ prc20Token, burnAmount: amount, gasToken,
325
342
  gasFee });
326
343
  }
327
344
  default:
@@ -553,15 +570,15 @@ function composeCascade(ctx, segments, ueaAddress, ueaBalance, ueaNonce) {
553
570
  ? new Uint8Array(Buffer.from(intermediatePayload.slice(2), 'hex'))
554
571
  : undefined,
555
572
  });
556
- const burnAmount = BigInt(1);
573
+ const svmBurnAmount = segment.totalBurnAmount || BigInt(0);
557
574
  const outboundReq = (0, payload_builders_1.buildOutboundRequest)(gatewayProgramHex, segment.prc20Token ||
558
- (0, helpers_1.getNativePRC20ForChain)(sourceChain, ctx.pushNetwork), burnAmount, (_g = segment.gasLimit) !== null && _g !== void 0 ? _g : BigInt(0), svmPayload, ueaAddress);
575
+ (0, helpers_1.getNativePRC20ForChain)(sourceChain, ctx.pushNetwork), svmBurnAmount, (_g = segment.gasLimit) !== null && _g !== void 0 ? _g : BigInt(0), svmPayload, ueaAddress);
559
576
  const inboundGasFee = segment.gasFee || BigInt(0);
560
577
  const outboundMulticalls = (0, payload_builders_1.buildOutboundApprovalAndCall)({
561
578
  prc20Token: segment.prc20Token ||
562
579
  (0, helpers_1.getNativePRC20ForChain)(sourceChain, ctx.pushNetwork),
563
580
  gasToken: segment.gasToken || selectors_1.ZERO_ADDRESS,
564
- burnAmount,
581
+ burnAmount: svmBurnAmount,
565
582
  gasFee: inboundGasFee,
566
583
  nativeValueForGas: perOutboundNativeValue !== null && perOutboundNativeValue !== void 0 ? perOutboundNativeValue : inboundGasFee * BigInt(1000),
567
584
  gatewayPcAddress,
@@ -628,13 +645,13 @@ function composeCascade(ctx, segments, ueaAddress, ueaBalance, ueaNonce) {
628
645
  // Wrap CEA multicall in outbound from Push Chain
629
646
  const ceaPayload = (0, payload_builders_1.buildCeaMulticallPayload)(ceaMulticalls);
630
647
  const outboundReq = (0, payload_builders_1.buildOutboundRequest)(ceaAddress, segment.prc20Token ||
631
- (0, helpers_1.getNativePRC20ForChain)(sourceChain, ctx.pushNetwork), segment.totalBurnAmount || BigInt(1), (_j = segment.gasLimit) !== null && _j !== void 0 ? _j : BigInt(0), ceaPayload, ueaAddress);
648
+ (0, helpers_1.getNativePRC20ForChain)(sourceChain, ctx.pushNetwork), segment.totalBurnAmount || BigInt(0), (_j = segment.gasLimit) !== null && _j !== void 0 ? _j : BigInt(0), ceaPayload, ueaAddress);
632
649
  const inboundGasFee = segment.gasFee || BigInt(0);
633
650
  const outboundMulticalls = (0, payload_builders_1.buildOutboundApprovalAndCall)({
634
651
  prc20Token: segment.prc20Token ||
635
652
  (0, helpers_1.getNativePRC20ForChain)(sourceChain, ctx.pushNetwork),
636
653
  gasToken: segment.gasToken || selectors_1.ZERO_ADDRESS,
637
- burnAmount: segment.totalBurnAmount || BigInt(1),
654
+ burnAmount: segment.totalBurnAmount || BigInt(0),
638
655
  gasFee: inboundGasFee,
639
656
  nativeValueForGas: perOutboundNativeValue !== null && perOutboundNativeValue !== void 0 ? perOutboundNativeValue : inboundGasFee * BigInt(1000),
640
657
  gatewayPcAddress,
@@ -653,7 +670,6 @@ function composeCascade(ctx, segments, ueaAddress, ueaBalance, ueaNonce) {
653
670
  // ============================================================================
654
671
  function createCascadedBuilder(ctx, preparedTxs, callbacks) {
655
672
  return {
656
- thenOn: (nextTx) => createCascadedBuilder(ctx, [...preparedTxs, nextTx], callbacks),
657
673
  send: () => tslib_1.__awaiter(this, void 0, void 0, function* () {
658
674
  const ueaAddress = (0, uea_manager_1.computeUEAOffchain)(ctx);
659
675
  // Extract HopDescriptors
@@ -198,7 +198,11 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
198
198
  const fixedPushAmount = utils_1.Utils.helpers.parseUnits('0.001', 18);
199
199
  const lockAmount = funds < requiredFunds ? fundDifference : fixedPushAmount;
200
200
  const lockAmountInUSD = ctx.pushClient.pushToUSDC(lockAmount);
201
- const feeLockTxHashBytes = yield (0, gateway_client_1.lockFee)(ctx, lockAmountInUSD, universalPayload, req);
201
+ // Apply minimum deposit override (e.g., Route 2 needs enough UPC for outbound swap)
202
+ const effectiveLockAmountInUSD = execute._minimumDepositUsd && execute._minimumDepositUsd > lockAmountInUSD
203
+ ? execute._minimumDepositUsd
204
+ : lockAmountInUSD;
205
+ const feeLockTxHashBytes = yield (0, gateway_client_1.lockFee)(ctx, effectiveLockAmountInUSD, universalPayload, req);
202
206
  feeLockTxHash = (0, viem_1.bytesToHex)(feeLockTxHashBytes);
203
207
  verificationData = (0, viem_1.bytesToHex)(feeLockTxHashBytes);
204
208
  const { vm } = chain_1.CHAIN_INFO[chain];
@@ -13,7 +13,15 @@ export declare function queryOutboundGasFee(ctx: OrchestratorContext, prc20Token
13
13
  protocolFee: bigint;
14
14
  nativeValueForGas: bigint;
15
15
  gasPrice: bigint;
16
+ universalCoreAddress: `0x${string}`;
16
17
  }>;
18
+ /**
19
+ * Estimate the native WPC amount needed to swap for `gasFee` of `gasToken`
20
+ * by reading the Uniswap V3 pool price on Push Chain.
21
+ * Returns the estimated amount with a 2x safety buffer (excess is refunded by the contract).
22
+ * Falls back to a percentage of accountBalance if any on-chain query fails.
23
+ */
24
+ export declare function estimateNativeValueForSwap(ctx: OrchestratorContext, universalCoreAddress: `0x${string}`, gasToken: `0x${string}`, gasFee: bigint, accountBalance: bigint): Promise<bigint>;
17
25
  export declare function queryRescueGasFee(ctx: OrchestratorContext, prc20Token: `0x${string}`): Promise<{
18
26
  gasToken: `0x${string}`;
19
27
  gasFee: bigint;
@@ -28,3 +36,12 @@ export declare function calculateGasAmountFromAmountOutMinETH(ctx: OrchestratorC
28
36
  }) => Promise<ConversionQuote>): Promise<{
29
37
  gasAmount: bigint;
30
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>;
@@ -6,9 +6,11 @@
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.ensureErc20Allowance = ensureErc20Allowance;
8
8
  exports.queryOutboundGasFee = queryOutboundGasFee;
9
+ exports.estimateNativeValueForSwap = estimateNativeValueForSwap;
9
10
  exports.queryRescueGasFee = queryRescueGasFee;
10
11
  exports.calculateNativeAmountForDeposit = calculateNativeAmountForDeposit;
11
12
  exports.calculateGasAmountFromAmountOutMinETH = calculateGasAmountFromAmountOutMinETH;
13
+ exports.estimateDepositFromLockedNative = estimateDepositFromLockedNative;
12
14
  const tslib_1 = require("tslib");
13
15
  const web3_js_1 = require("@solana/web3.js");
14
16
  const viem_1 = require("viem");
@@ -24,6 +26,43 @@ const context_1 = require("./context");
24
26
  const helpers_1 = require("./helpers");
25
27
  /** Buffer multiplier for nativeValueForGas. Excess is refunded by swapAndBurnGas to the UEA. */
26
28
  const GAS_FEE_BUFFER_MULTIPLIER = BigInt(1000000);
29
+ // Minimal ABIs for Uniswap V3 pool price estimation
30
+ const UNISWAP_V3_POOL_SLOT0_ABI = [
31
+ {
32
+ type: 'function',
33
+ name: 'slot0',
34
+ inputs: [],
35
+ outputs: [
36
+ { name: 'sqrtPriceX96', type: 'uint160', internalType: 'uint160' },
37
+ { name: 'tick', type: 'int24', internalType: 'int24' },
38
+ { name: 'observationIndex', type: 'uint16', internalType: 'uint16' },
39
+ { name: 'observationCardinality', type: 'uint16', internalType: 'uint16' },
40
+ { name: 'observationCardinalityNext', type: 'uint16', internalType: 'uint16' },
41
+ { name: 'feeProtocol', type: 'uint8', internalType: 'uint8' },
42
+ { name: 'unlocked', type: 'bool', internalType: 'bool' },
43
+ ],
44
+ stateMutability: 'view',
45
+ },
46
+ ];
47
+ const UNISWAP_V3_FACTORY_ABI = [
48
+ {
49
+ type: 'function',
50
+ name: 'getPool',
51
+ inputs: [
52
+ { name: 'tokenA', type: 'address', internalType: 'address' },
53
+ { name: 'tokenB', type: 'address', internalType: 'address' },
54
+ { name: 'fee', type: 'uint24', internalType: 'uint24' },
55
+ ],
56
+ outputs: [{ name: 'pool', type: 'address', internalType: 'address' }],
57
+ stateMutability: 'view',
58
+ },
59
+ ];
60
+ const UNIVERSAL_CORE_SWAP_HELPERS_ABI = [
61
+ { type: 'function', name: 'WPC', inputs: [], outputs: [{ name: '', type: 'address', internalType: 'address' }], stateMutability: 'view' },
62
+ { type: 'function', name: 'uniswapV3Factory', inputs: [], outputs: [{ name: '', type: 'address', internalType: 'address' }], stateMutability: 'view' },
63
+ { type: 'function', name: 'defaultFeeTier', inputs: [{ name: '', type: 'address', internalType: 'address' }], outputs: [{ name: '', type: 'uint24', internalType: 'uint24' }], stateMutability: 'view' },
64
+ ];
65
+ const ZERO_ADDR = '0x0000000000000000000000000000000000000000';
27
66
  // ============================================================================
28
67
  // ERC-20 Allowance
29
68
  // ============================================================================
@@ -136,10 +175,113 @@ function queryOutboundGasFee(ctx, prc20Token, gasLimit) {
136
175
  }
137
176
  const nativeValueForGas = protocolFee + gasFee * GAS_FEE_BUFFER_MULTIPLIER;
138
177
  (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 5] using 1000000x buffer: nativeValueForGas=${nativeValueForGas}`);
139
- return { gasToken, gasFee, protocolFee, nativeValueForGas, gasPrice };
178
+ return { gasToken, gasFee, protocolFee, nativeValueForGas, gasPrice, universalCoreAddress };
140
179
  });
141
180
  }
142
181
  // ============================================================================
182
+ // Uniswap V3 Pool Price Estimation
183
+ // ============================================================================
184
+ /**
185
+ * Estimate the native WPC amount needed to swap for `gasFee` of `gasToken`
186
+ * by reading the Uniswap V3 pool price on Push Chain.
187
+ * Returns the estimated amount with a 2x safety buffer (excess is refunded by the contract).
188
+ * Falls back to a percentage of accountBalance if any on-chain query fails.
189
+ */
190
+ function estimateNativeValueForSwap(ctx, universalCoreAddress, gasToken, gasFee, accountBalance) {
191
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
192
+ const SWAP_BUFFER = BigInt(2); // 2x safety buffer; excess is refunded by swapAndBurnGas
193
+ const BALANCE_FALLBACK_DIVISOR = BigInt(10); // 10% of balance as fallback
194
+ const GAS_RESERVE = BigInt(3e18); // 3 UPC reserve for tx overhead
195
+ try {
196
+ // Read WPC, factory, and defaultFeeTier in parallel
197
+ const [wpcAddress, factoryAddress, feeTier] = yield Promise.all([
198
+ ctx.pushClient.readContract({
199
+ address: universalCoreAddress,
200
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
201
+ functionName: 'WPC',
202
+ args: [],
203
+ }),
204
+ ctx.pushClient.readContract({
205
+ address: universalCoreAddress,
206
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
207
+ functionName: 'uniswapV3Factory',
208
+ args: [],
209
+ }),
210
+ ctx.pushClient.readContract({
211
+ address: universalCoreAddress,
212
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
213
+ functionName: 'defaultFeeTier',
214
+ args: [gasToken],
215
+ }),
216
+ ]);
217
+ if (!feeTier) {
218
+ (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — no fee tier for gasToken, using balance fallback`);
219
+ return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
220
+ }
221
+ // Get pool address from factory
222
+ const poolAddress = yield ctx.pushClient.readContract({
223
+ address: factoryAddress,
224
+ abi: UNISWAP_V3_FACTORY_ABI,
225
+ functionName: 'getPool',
226
+ args: [wpcAddress, gasToken, feeTier],
227
+ });
228
+ if (poolAddress === ZERO_ADDR) {
229
+ (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — pool not found, using balance fallback`);
230
+ return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
231
+ }
232
+ // Read slot0 for current price
233
+ const slot0 = yield ctx.pushClient.readContract({
234
+ address: poolAddress,
235
+ abi: UNISWAP_V3_POOL_SLOT0_ABI,
236
+ functionName: 'slot0',
237
+ args: [],
238
+ });
239
+ const sqrtPriceX96 = slot0[0];
240
+ if (!sqrtPriceX96 || sqrtPriceX96 === BigInt(0)) {
241
+ (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — pool not initialized, using balance fallback`);
242
+ return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
243
+ }
244
+ // price (token1/token0 in raw units) = (sqrtPriceX96)² / 2¹⁹²
245
+ const Q192 = BigInt(1) << BigInt(192);
246
+ const priceNum = sqrtPriceX96 * sqrtPriceX96; // sqrtPrice² in Q192
247
+ // Uniswap V3 sorts tokens: token0 < token1 by address
248
+ const isGasTokenToken0 = gasToken.toLowerCase() < wpcAddress.toLowerCase();
249
+ let wpcNeeded;
250
+ if (isGasTokenToken0) {
251
+ // price = WPC_per_gasToken → wpcNeeded = gasFee * price
252
+ wpcNeeded = (gasFee * priceNum) / Q192;
253
+ }
254
+ else {
255
+ // price = gasToken_per_WPC → wpcNeeded = gasFee / price
256
+ wpcNeeded = (gasFee * Q192) / priceNum;
257
+ }
258
+ const result = wpcNeeded * SWAP_BUFFER;
259
+ (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — pool=${poolAddress}, sqrtPriceX96=${sqrtPriceX96}, ` +
260
+ `wpcNeeded=${wpcNeeded}, withBuffer(2x)=${result}`);
261
+ // Cap at (balance - reserve)
262
+ if (accountBalance > result + GAS_RESERVE) {
263
+ return result;
264
+ }
265
+ else if (accountBalance > GAS_RESERVE) {
266
+ return accountBalance - GAS_RESERVE;
267
+ }
268
+ return result; // let caller decide if balance is too low
269
+ }
270
+ catch (err) {
271
+ (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — failed: ${err instanceof Error ? err.message : String(err)}, using balance fallback`);
272
+ return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
273
+ }
274
+ });
275
+ }
276
+ function balanceFallback(balance, divisor, reserve) {
277
+ const fraction = balance / divisor;
278
+ if (balance > fraction + reserve)
279
+ return fraction;
280
+ if (balance > reserve)
281
+ return balance - reserve;
282
+ return fraction;
283
+ }
284
+ // ============================================================================
143
285
  // Rescue Gas Fee Query
144
286
  // ============================================================================
145
287
  function queryRescueGasFee(ctx, prc20Token) {
@@ -280,4 +422,97 @@ function calculateGasAmountFromAmountOutMinETH(ctx, gasTokenAddress, amountOutMi
280
422
  return { gasAmount };
281
423
  });
282
424
  }
425
+ // ============================================================================
426
+ // Estimate UPC deposit from locked ETH via Uniswap V3 quote
427
+ // ============================================================================
428
+ /**
429
+ * Predicts how much UPC (WPC) the chain will deposit to the UEA from a given
430
+ * amount of locked native token (e.g., ETH on Sepolia). The chain converts
431
+ * locked ETH → pETH (PRC-20) → WPC via Uniswap V3 swap on Push Chain.
432
+ *
433
+ * Queries the same Uniswap V3 QuoterV2 the chain uses in execute_inbound_gas.go.
434
+ * Returns 0 on any failure (caller should fall back to other logic).
435
+ */
436
+ function estimateDepositFromLockedNative(ctx, nativeAmountForLocker, prc20Token) {
437
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
438
+ var _a, _b;
439
+ try {
440
+ const pushChain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
441
+ 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;
442
+ if (!quoterAddress || quoterAddress.startsWith('0xTBD'))
443
+ return BigInt(0);
444
+ // Get UniversalCore → WPC address + fee tier (reuses existing ABI)
445
+ const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
446
+ const universalCoreAddress = yield ctx.pushClient.readContract({
447
+ address: gatewayPcAddress,
448
+ abi: abi_1.UNIVERSAL_GATEWAY_PC,
449
+ functionName: 'UNIVERSAL_CORE',
450
+ args: [],
451
+ });
452
+ const [wpcAddress, feeTier] = yield Promise.all([
453
+ ctx.pushClient.readContract({
454
+ address: universalCoreAddress,
455
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
456
+ functionName: 'WPC',
457
+ args: [],
458
+ }),
459
+ ctx.pushClient.readContract({
460
+ address: universalCoreAddress,
461
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
462
+ functionName: 'defaultFeeTier',
463
+ args: [prc20Token],
464
+ }),
465
+ ]);
466
+ if (!feeTier || !wpcAddress)
467
+ return BigInt(0);
468
+ // QuoterV2.quoteExactInputSingle — same call the chain relay makes
469
+ const QUOTER_ABI = [
470
+ {
471
+ type: 'function',
472
+ name: 'quoteExactInputSingle',
473
+ inputs: [
474
+ {
475
+ type: 'tuple',
476
+ components: [
477
+ { name: 'tokenIn', type: 'address' },
478
+ { name: 'tokenOut', type: 'address' },
479
+ { name: 'amountIn', type: 'uint256' },
480
+ { name: 'fee', type: 'uint24' },
481
+ { name: 'sqrtPriceLimitX96', type: 'uint160' },
482
+ ],
483
+ },
484
+ ],
485
+ outputs: [
486
+ { name: 'amountOut', type: 'uint256' },
487
+ { name: 'sqrtPriceX96After', type: 'uint160' },
488
+ { name: 'initializedTicksCrossed', type: 'uint32' },
489
+ { name: 'gasEstimate', type: 'uint256' },
490
+ ],
491
+ stateMutability: 'view',
492
+ },
493
+ ];
494
+ const result = yield ctx.pushClient.readContract({
495
+ address: quoterAddress,
496
+ abi: QUOTER_ABI,
497
+ functionName: 'quoteExactInputSingle',
498
+ args: [
499
+ {
500
+ tokenIn: prc20Token,
501
+ tokenOut: wpcAddress,
502
+ amountIn: nativeAmountForLocker,
503
+ fee: feeTier,
504
+ sqrtPriceLimitX96: BigInt(0),
505
+ },
506
+ ],
507
+ });
508
+ const amountOut = result[0];
509
+ (0, context_1.printLog)(ctx, `estimateDepositFromLockedNative — quote: ${nativeAmountForLocker.toString()} pETH → ${amountOut.toString()} WPC (fee tier: ${feeTier})`);
510
+ return amountOut;
511
+ }
512
+ catch (err) {
513
+ (0, context_1.printLog)(ctx, `estimateDepositFromLockedNative — failed: ${err instanceof Error ? err.message : String(err)}`);
514
+ return BigInt(0);
515
+ }
516
+ });
517
+ }
283
518
  //# sourceMappingURL=gas-calculator.js.map
@@ -27,6 +27,7 @@ const context_1 = require("./context");
27
27
  */
28
28
  function sendPushTx(ctx, execute, eventBuffer, transformFn) {
29
29
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
30
+ var _a, _b, _c;
30
31
  if (Array.isArray(execute.data)) {
31
32
  const PUSH_CHAIN_GAS_LIMIT = BigInt(500000);
32
33
  const MAX_NONCE_RETRIES = 3;
@@ -73,7 +74,29 @@ function sendPushTx(ctx, execute, eventBuffer, transformFn) {
73
74
  hash: lastTxHash,
74
75
  });
75
76
  if (receipt.status === 'reverted') {
76
- throw new Error(`sendPushTx — multicall operation ${i + 1}/${calls.length} reverted (to: ${call.to}, txHash: ${lastTxHash})`);
77
+ // Simulate the failed call to extract the revert reason
78
+ let revertReason = 'unknown';
79
+ try {
80
+ yield ctx.pushClient.publicClient.call({
81
+ to: call.to,
82
+ data: (call.data || '0x'),
83
+ value: call.value,
84
+ account: ctx.universalSigner.account.address,
85
+ blockNumber: receipt.blockNumber,
86
+ });
87
+ }
88
+ catch (simErr) {
89
+ // viem decodes common revert reasons into shortMessage
90
+ revertReason =
91
+ (simErr === null || simErr === void 0 ? void 0 : simErr.shortMessage) || ((_a = simErr === null || simErr === void 0 ? void 0 : simErr.cause) === null || _a === void 0 ? void 0 : _a.reason) || ((_b = simErr === null || simErr === void 0 ? void 0 : simErr.cause) === null || _b === void 0 ? void 0 : _b.message) || (simErr === null || simErr === void 0 ? void 0 : simErr.message) || String(simErr);
92
+ // Also log the raw revert data if available
93
+ const revertData = ((_c = simErr === null || simErr === void 0 ? void 0 : simErr.cause) === null || _c === void 0 ? void 0 : _c.data) || (simErr === null || simErr === void 0 ? void 0 : simErr.data);
94
+ if (revertData) {
95
+ revertReason += ` [data: ${revertData}]`;
96
+ }
97
+ }
98
+ (0, context_1.printLog)(ctx, `sendPushTx — multicall operation ${i + 1}/${calls.length} reverted (to: ${call.to}, txHash: ${lastTxHash}, revertReason: ${revertReason})`);
99
+ throw new Error(`sendPushTx — multicall operation ${i + 1}/${calls.length} reverted (to: ${call.to}, txHash: ${lastTxHash}, revertReason: ${revertReason})`);
77
100
  }
78
101
  (0, context_1.printLog)(ctx, `sendPushTx — operation ${i + 1}/${calls.length} confirmed in block ${receipt.blockNumber}`);
79
102
  nonce++;