@pushchain/core 6.0.19 → 6.0.21

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 (112) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/package.json +1 -1
  3. package/src/lib/cache/cache.js +2 -0
  4. package/src/lib/constants/abi/index.d.ts +1 -0
  5. package/src/lib/constants/abi/index.js +8 -1
  6. package/src/lib/constants/abi/pc20.evm.d.ts +217 -0
  7. package/src/lib/constants/abi/pc20.evm.js +150 -0
  8. package/src/lib/constants/abi/prc20.evm.d.ts +172 -0
  9. package/src/lib/constants/abi/prc20.evm.js +97 -0
  10. package/src/lib/constants/abi/universalGatewayV0.json +1 -1
  11. package/src/lib/constants/chain.js +38 -8
  12. package/src/lib/constants/selectors.js +2 -2
  13. package/src/lib/constants/tokens.js +4 -3
  14. package/src/lib/formatters.js +16 -6
  15. package/src/lib/generated/uexecutor/v1/query.js +2 -4
  16. package/src/lib/generated/uexecutor/v1/types.d.ts +14 -0
  17. package/src/lib/generated/uexecutor/v1/types.js +90 -47
  18. package/src/lib/generated/uexecutor/v2/query.js +2 -4
  19. package/src/lib/generated/uexecutor/v2/types.d.ts +20 -0
  20. package/src/lib/generated/uexecutor/v2/types.js +49 -33
  21. package/src/lib/generated/v1/tx.js +30 -37
  22. package/src/lib/index.d.ts +4 -1
  23. package/src/lib/index.js +21 -3
  24. package/src/lib/internal/buffer.js +1 -2
  25. package/src/lib/orchestrator/cea-utils.js +73 -83
  26. package/src/lib/orchestrator/internals/account-manager.js +130 -139
  27. package/src/lib/orchestrator/internals/cascade.d.ts +0 -6
  28. package/src/lib/orchestrator/internals/cascade.js +1184 -1059
  29. package/src/lib/orchestrator/internals/confirmation.js +138 -148
  30. package/src/lib/orchestrator/internals/error-decoder.js +1 -1
  31. package/src/lib/orchestrator/internals/errors.js +12 -3
  32. package/src/lib/orchestrator/internals/execute-funds-only.d.ts +2 -2
  33. package/src/lib/orchestrator/internals/execute-funds-only.js +297 -259
  34. package/src/lib/orchestrator/internals/execute-funds-payload.d.ts +2 -2
  35. package/src/lib/orchestrator/internals/execute-funds-payload.js +220 -220
  36. package/src/lib/orchestrator/internals/execute-standard.d.ts +0 -8
  37. package/src/lib/orchestrator/internals/execute-standard.js +339 -342
  38. package/src/lib/orchestrator/internals/gas-calculator.js +497 -520
  39. package/src/lib/orchestrator/internals/gas-usd-sizer.js +101 -110
  40. package/src/lib/orchestrator/internals/gateway-client.js +102 -103
  41. package/src/lib/orchestrator/internals/helpers.js +30 -27
  42. package/src/lib/orchestrator/internals/inbound-tracker.js +234 -238
  43. package/src/lib/orchestrator/internals/outbound-sync.js +463 -452
  44. package/src/lib/orchestrator/internals/outbound-tracker.js +27 -34
  45. package/src/lib/orchestrator/internals/payload-builder.d.ts +2 -2
  46. package/src/lib/orchestrator/internals/payload-builder.js +119 -100
  47. package/src/lib/orchestrator/internals/pc-usd-oracle.js +121 -129
  48. package/src/lib/orchestrator/internals/pc20/address-codec.d.ts +31 -0
  49. package/src/lib/orchestrator/internals/pc20/address-codec.js +124 -0
  50. package/src/lib/orchestrator/internals/pc20/chain-namespace.d.ts +68 -0
  51. package/src/lib/orchestrator/internals/pc20/chain-namespace.js +136 -0
  52. package/src/lib/orchestrator/internals/pc20/errors.d.ts +160 -0
  53. package/src/lib/orchestrator/internals/pc20/errors.js +236 -0
  54. package/src/lib/orchestrator/internals/pc20/export.d.ts +172 -0
  55. package/src/lib/orchestrator/internals/pc20/export.js +412 -0
  56. package/src/lib/orchestrator/internals/pc20/gate.d.ts +67 -0
  57. package/src/lib/orchestrator/internals/pc20/gate.js +184 -0
  58. package/src/lib/orchestrator/internals/pc20/resolver.d.ts +187 -0
  59. package/src/lib/orchestrator/internals/pc20/resolver.js +658 -0
  60. package/src/lib/orchestrator/internals/pc20/svm.d.ts +189 -0
  61. package/src/lib/orchestrator/internals/pc20/svm.js +286 -0
  62. package/src/lib/orchestrator/internals/pc20/tracking.d.ts +46 -0
  63. package/src/lib/orchestrator/internals/pc20/tracking.js +109 -0
  64. package/src/lib/orchestrator/internals/preflight.js +1 -1
  65. package/src/lib/orchestrator/internals/progress-route-hooks.js +2 -2
  66. package/src/lib/orchestrator/internals/push-chain-tx.js +319 -331
  67. package/src/lib/orchestrator/internals/quote.js +90 -94
  68. package/src/lib/orchestrator/internals/rescue.js +76 -79
  69. package/src/lib/orchestrator/internals/response-builder.d.ts +28 -1
  70. package/src/lib/orchestrator/internals/response-builder.js +817 -701
  71. package/src/lib/orchestrator/internals/route-handlers.d.ts +7 -15
  72. package/src/lib/orchestrator/internals/route-handlers.js +1512 -1178
  73. package/src/lib/orchestrator/internals/signing.js +78 -83
  74. package/src/lib/orchestrator/internals/svm-bridge.d.ts +2 -2
  75. package/src/lib/orchestrator/internals/svm-bridge.js +161 -93
  76. package/src/lib/orchestrator/internals/svm-helpers.d.ts +15 -1
  77. package/src/lib/orchestrator/internals/svm-helpers.js +68 -24
  78. package/src/lib/orchestrator/internals/svm-rent.d.ts +19 -1
  79. package/src/lib/orchestrator/internals/svm-rent.js +163 -141
  80. package/src/lib/orchestrator/internals/tx-transformer.js +26 -23
  81. package/src/lib/orchestrator/internals/uea-manager.js +89 -86
  82. package/src/lib/orchestrator/max-pc-for-gas.js +5 -6
  83. package/src/lib/orchestrator/orchestrator.js +217 -200
  84. package/src/lib/orchestrator/orchestrator.types.d.ts +121 -1
  85. package/src/lib/orchestrator/orchestrator.types.js +19 -0
  86. package/src/lib/orchestrator/payload-builders.d.ts +2 -2
  87. package/src/lib/orchestrator/payload-builders.js +26 -24
  88. package/src/lib/orchestrator/route-detector.js +26 -9
  89. package/src/lib/orchestrator/svm-idl/ix-encoder.js +1 -2
  90. package/src/lib/orchestrator/svm-idl/normalize-address.js +2 -2
  91. package/src/lib/orchestrator/svm-idl/resolve.js +1 -2
  92. package/src/lib/price-fetch/price-fetch.js +67 -68
  93. package/src/lib/progress-hook/progress-hook.js +124 -72
  94. package/src/lib/push-chain/push-chain.js +171 -153
  95. package/src/lib/push-client/push-client.js +223 -237
  96. package/src/lib/universal/account/account.js +349 -365
  97. package/src/lib/universal/signer/signer.d.ts +2 -1
  98. package/src/lib/universal/signer/signer.js +315 -299
  99. package/src/lib/universal-tx-detector/auto-detect.js +55 -60
  100. package/src/lib/universal-tx-detector/cascade.js +160 -172
  101. package/src/lib/universal-tx-detector/child-inbounds.js +67 -75
  102. package/src/lib/universal-tx-detector/classify.js +2 -3
  103. package/src/lib/universal-tx-detector/detector-svm.js +139 -147
  104. package/src/lib/universal-tx-detector/detector.js +145 -157
  105. package/src/lib/universal-tx-detector/normalize.js +7 -7
  106. package/src/lib/utils/external-tx-hash.js +1 -2
  107. package/src/lib/utils.d.ts +44 -0
  108. package/src/lib/utils.js +762 -683
  109. package/src/lib/vm-client/evm-client.js +186 -202
  110. package/src/lib/vm-client/svm-client.d.ts +1 -1
  111. package/src/lib/vm-client/svm-client.js +220 -224
  112. package/src/lib/vm-client/vm-client.types.d.ts +14 -2
@@ -13,7 +13,6 @@ exports.calculateNativeAmountForDeposit = calculateNativeAmountForDeposit;
13
13
  exports.calculateGasAmountFromAmountOutMinETH = calculateGasAmountFromAmountOutMinETH;
14
14
  exports.estimateDepositFromLockedNative = estimateDepositFromLockedNative;
15
15
  exports.estimateNativeForDesiredDeposit = estimateNativeForDesiredDeposit;
16
- const tslib_1 = require("tslib");
17
16
  const web3_js_1 = require("@solana/web3.js");
18
17
  const viem_1 = require("viem");
19
18
  const abi_1 = require("../../constants/abi");
@@ -99,142 +98,137 @@ const ZERO_ADDR = '0x0000000000000000000000000000000000000000';
99
98
  // ============================================================================
100
99
  // ERC-20 Allowance
101
100
  // ============================================================================
102
- function ensureErc20Allowance(ctx, evmClient, tokenAddress, spender, requiredAmount) {
103
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
104
- const chain = ctx.universalSigner.account.chain;
105
- const owner = ctx.universalSigner.account.address;
106
- const currentAllowance = yield evmClient.readContract({
107
- abi: abi_1.ERC20_EVM,
108
- address: tokenAddress,
109
- functionName: 'allowance',
110
- args: [owner, spender],
111
- });
112
- if (currentAllowance >= requiredAmount)
113
- return;
114
- if (currentAllowance > BigInt(0)) {
115
- (0, context_1.printLog)(ctx, `Resetting existing allowance from ${currentAllowance.toString()} to 0 for spender ${spender}`);
116
- const resetTxHash = yield evmClient.writeContract({
117
- abi: abi_1.ERC20_EVM,
118
- address: tokenAddress,
119
- functionName: 'approve',
120
- args: [spender, BigInt(0)],
121
- signer: ctx.universalSigner,
122
- });
123
- yield evmClient.waitForConfirmations({
124
- txHash: resetTxHash,
125
- confirmations: 1,
126
- timeoutMs: chain_1.CHAIN_INFO[chain].timeout,
127
- });
128
- }
129
- const setTxHash = yield evmClient.writeContract({
101
+ async function ensureErc20Allowance(ctx, evmClient, tokenAddress, spender, requiredAmount) {
102
+ const chain = ctx.universalSigner.account.chain;
103
+ const owner = ctx.universalSigner.account.address;
104
+ const currentAllowance = await evmClient.readContract({
105
+ abi: abi_1.ERC20_EVM,
106
+ address: tokenAddress,
107
+ functionName: 'allowance',
108
+ args: [owner, spender],
109
+ });
110
+ if (currentAllowance >= requiredAmount)
111
+ return;
112
+ if (currentAllowance > BigInt(0)) {
113
+ (0, context_1.printLog)(ctx, `Resetting existing allowance from ${currentAllowance.toString()} to 0 for spender ${spender}`);
114
+ const resetTxHash = await evmClient.writeContract({
130
115
  abi: abi_1.ERC20_EVM,
131
116
  address: tokenAddress,
132
117
  functionName: 'approve',
133
- args: [spender, requiredAmount],
118
+ args: [spender, BigInt(0)],
134
119
  signer: ctx.universalSigner,
135
120
  });
136
- yield evmClient.waitForConfirmations({
137
- txHash: setTxHash,
121
+ await evmClient.waitForConfirmations({
122
+ txHash: resetTxHash,
138
123
  confirmations: 1,
139
124
  timeoutMs: chain_1.CHAIN_INFO[chain].timeout,
140
125
  });
141
- try {
142
- const updated = yield evmClient.readContract({
143
- abi: abi_1.ERC20_EVM,
144
- address: tokenAddress,
145
- functionName: 'allowance',
146
- args: [owner, spender],
147
- });
148
- if (updated < requiredAmount) {
149
- (0, context_1.printLog)(ctx, 'Warning: allowance not updated yet; proceeding');
150
- }
151
- }
152
- catch (_a) {
153
- // ignore
154
- }
126
+ }
127
+ const setTxHash = await evmClient.writeContract({
128
+ abi: abi_1.ERC20_EVM,
129
+ address: tokenAddress,
130
+ functionName: 'approve',
131
+ args: [spender, requiredAmount],
132
+ signer: ctx.universalSigner,
155
133
  });
134
+ await evmClient.waitForConfirmations({
135
+ txHash: setTxHash,
136
+ confirmations: 1,
137
+ timeoutMs: chain_1.CHAIN_INFO[chain].timeout,
138
+ });
139
+ try {
140
+ const updated = await evmClient.readContract({
141
+ abi: abi_1.ERC20_EVM,
142
+ address: tokenAddress,
143
+ functionName: 'allowance',
144
+ args: [owner, spender],
145
+ });
146
+ if (updated < requiredAmount) {
147
+ (0, context_1.printLog)(ctx, 'Warning: allowance not updated yet; proceeding');
148
+ }
149
+ }
150
+ catch {
151
+ // ignore
152
+ }
156
153
  }
157
154
  // ============================================================================
158
155
  // Outbound Gas Fee Query
159
156
  // ============================================================================
160
- function queryOutboundGasFee(ctx, prc20Token, gasLimit, destinationChain) {
161
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
162
- var _a, _b, _c;
163
- const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
164
- const pushChain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
165
- 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';
166
- (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 1] inputs: gateway=${gatewayPcAddress}, prc20Token=${prc20Token}, gasLimit=${gasLimit}, rpcUrl=${rpcUrl}`);
167
- let universalCoreAddress;
168
- try {
169
- universalCoreAddress = yield ctx.pushClient.readContract({
170
- address: gatewayPcAddress,
171
- abi: abi_1.UNIVERSAL_GATEWAY_PC,
172
- functionName: 'universalCore',
173
- args: [],
174
- });
175
- (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 2] universalCore resolved to: ${universalCoreAddress}`);
176
- }
177
- catch (err) {
178
- (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 2] FAILED to read universalCore: ${err instanceof Error ? err.message : String(err)}`);
179
- throw err;
180
- }
181
- const callData = (0, viem_1.encodeFunctionData)({
157
+ async function queryOutboundGasFee(ctx, prc20Token, gasLimit, destinationChain) {
158
+ const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
159
+ const pushChain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
160
+ const rpcUrl = chain_1.CHAIN_INFO[pushChain]?.defaultRPC?.[0] || 'unknown';
161
+ (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 1] inputs: gateway=${gatewayPcAddress}, prc20Token=${prc20Token}, gasLimit=${gasLimit}, rpcUrl=${rpcUrl}`);
162
+ let universalCoreAddress;
163
+ try {
164
+ universalCoreAddress = await ctx.pushClient.readContract({
165
+ address: gatewayPcAddress,
166
+ abi: abi_1.UNIVERSAL_GATEWAY_PC,
167
+ functionName: 'universalCore',
168
+ args: [],
169
+ });
170
+ (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 2] universalCore resolved to: ${universalCoreAddress}`);
171
+ }
172
+ catch (err) {
173
+ (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 2] FAILED to read universalCore: ${err instanceof Error ? err.message : String(err)}`);
174
+ throw err;
175
+ }
176
+ const callData = (0, viem_1.encodeFunctionData)({
177
+ abi: abi_1.UNIVERSAL_CORE_EVM,
178
+ functionName: 'getOutboundTxGasAndFees',
179
+ args: [prc20Token, gasLimit],
180
+ });
181
+ (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 3] calling getOutboundTxGasAndFees on ${universalCoreAddress}`);
182
+ (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 3] eth_call: {"method":"eth_call","params":[{"to":"${universalCoreAddress}","data":"${callData}"},"latest"]}`);
183
+ let gasToken;
184
+ let gasFee;
185
+ let protocolFee;
186
+ let gasPrice = BigInt(0);
187
+ let gasLimitUsed = gasLimit;
188
+ try {
189
+ const result = await ctx.pushClient.readContract({
190
+ address: universalCoreAddress,
182
191
  abi: abi_1.UNIVERSAL_CORE_EVM,
183
192
  functionName: 'getOutboundTxGasAndFees',
184
193
  args: [prc20Token, gasLimit],
185
194
  });
186
- (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 3] calling getOutboundTxGasAndFees on ${universalCoreAddress}`);
187
- (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 3] eth_call: {"method":"eth_call","params":[{"to":"${universalCoreAddress}","data":"${callData}"},"latest"]}`);
188
- let gasToken;
189
- let gasFee;
190
- let protocolFee;
191
- let gasPrice = BigInt(0);
192
- let gasLimitUsed = gasLimit;
195
+ gasToken = result[0];
196
+ gasFee = result[1];
197
+ protocolFee = result[2];
198
+ gasPrice = result[3];
199
+ gasLimitUsed = result[5] ?? gasLimit;
200
+ (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 4] success: gasToken=${gasToken}, gasFee=${gasFee}, protocolFee=${protocolFee}, gasPrice=${gasPrice}, gasLimitUsed=${gasLimitUsed}`);
201
+ }
202
+ catch (err) {
203
+ (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 3] FAILED: ${err instanceof Error ? err.message : String(err)}`);
204
+ throw err;
205
+ }
206
+ let nativeValueForGas;
207
+ let sizing;
208
+ if (destinationChain !== undefined) {
193
209
  try {
194
- const result = yield ctx.pushClient.readContract({
195
- address: universalCoreAddress,
196
- abi: abi_1.UNIVERSAL_CORE_EVM,
197
- functionName: 'getOutboundTxGasAndFees',
198
- args: [prc20Token, gasLimit],
210
+ sizing = await (0, gas_usd_sizer_1.sizeOutboundGas)(ctx, {
211
+ gasFee,
212
+ originChain: ctx.universalSigner.account.chain,
213
+ destinationChain,
199
214
  });
200
- gasToken = result[0];
201
- gasFee = result[1];
202
- protocolFee = result[2];
203
- gasPrice = result[3];
204
- gasLimitUsed = (_c = result[5]) !== null && _c !== void 0 ? _c : gasLimit;
205
- (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 4] success: gasToken=${gasToken}, gasFee=${gasFee}, protocolFee=${protocolFee}, gasPrice=${gasPrice}, gasLimitUsed=${gasLimitUsed}`);
215
+ // All categories — A, B, and C — return the sizer's calibrated gas leg.
216
+ // R3 consumers additionally bump `nativeValueForGas` by `overflowNativePc`
217
+ // when category === 'C' (see route-handlers.executeCeaToPush).
218
+ nativeValueForGas = sizing.gasLegNativePc + protocolFee;
219
+ (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 5] sizer: category=${sizing.category}, gasUsd=${sizing.gasUsd}, ` +
220
+ `gasLegNativePc=${sizing.gasLegNativePc}, overflowNativePc=${sizing.overflowNativePc}, nativeValueForGas=${nativeValueForGas}`);
206
221
  }
207
222
  catch (err) {
208
- (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 3] FAILED: ${err instanceof Error ? err.message : String(err)}`);
209
- throw err;
210
- }
211
- let nativeValueForGas;
212
- let sizing;
213
- if (destinationChain !== undefined) {
214
- try {
215
- sizing = yield (0, gas_usd_sizer_1.sizeOutboundGas)(ctx, {
216
- gasFee,
217
- originChain: ctx.universalSigner.account.chain,
218
- destinationChain,
219
- });
220
- // All categories — A, B, and C — return the sizer's calibrated gas leg.
221
- // R3 consumers additionally bump `nativeValueForGas` by `overflowNativePc`
222
- // when category === 'C' (see route-handlers.executeCeaToPush).
223
- nativeValueForGas = sizing.gasLegNativePc + protocolFee;
224
- (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 5] sizer: category=${sizing.category}, gasUsd=${sizing.gasUsd}, ` +
225
- `gasLegNativePc=${sizing.gasLegNativePc}, overflowNativePc=${sizing.overflowNativePc}, nativeValueForGas=${nativeValueForGas}`);
226
- }
227
- catch (err) {
228
- (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 5] sizer failed (${err instanceof Error ? err.message : String(err)}); falling back to 1M buffer`);
229
- nativeValueForGas = protocolFee + gasFee * GAS_FEE_BUFFER_MULTIPLIER;
230
- }
231
- }
232
- else {
223
+ (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 5] sizer failed (${err instanceof Error ? err.message : String(err)}); falling back to 1M buffer`);
233
224
  nativeValueForGas = protocolFee + gasFee * GAS_FEE_BUFFER_MULTIPLIER;
234
- (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 5] no destinationChain provided; legacy 1M buffer: nativeValueForGas=${nativeValueForGas}`);
235
225
  }
236
- return { gasToken, gasFee, protocolFee, nativeValueForGas, gasPrice, gasLimitUsed, universalCoreAddress, sizing };
237
- });
226
+ }
227
+ else {
228
+ nativeValueForGas = protocolFee + gasFee * GAS_FEE_BUFFER_MULTIPLIER;
229
+ (0, context_1.printLog)(ctx, `queryOutboundGasFee — [step 5] no destinationChain provided; legacy 1M buffer: nativeValueForGas=${nativeValueForGas}`);
230
+ }
231
+ return { gasToken, gasFee, protocolFee, nativeValueForGas, gasPrice, gasLimitUsed, universalCoreAddress, sizing };
238
232
  }
239
233
  // ============================================================================
240
234
  // Uniswap V3 Pool Price Estimation
@@ -245,124 +239,121 @@ function queryOutboundGasFee(ctx, prc20Token, gasLimit, destinationChain) {
245
239
  * Returns the estimated amount with a 2x safety buffer (excess is refunded by the contract).
246
240
  * Falls back to a percentage of accountBalance if any on-chain query fails.
247
241
  */
248
- function estimateNativeValueForSwap(ctx, universalCoreAddress, gasToken, gasFee, accountBalance) {
249
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
250
- var _a, _b;
251
- // 2.2x safety buffer applied to the pool quote; excess is refunded by
252
- // swapAndBurnGas. Composed of a 2x pool-slippage cushion plus 10%
253
- // headroom that used to live in the R2 route-handler callers (×110/100
254
- // after this function returned). Folded into one place here so the cap
255
- // branch below correctly bounds the FINAL inflated value — the previous
256
- // arrangement (outer ×1.10 on top of an inner cap that returned
257
- // `balance - GAS_RESERVE`) caused a deterministic preflight failure
258
- // whenever the cap fired: required = 1.10 × (balance − 3 PC) + 3 PC ≈
259
- // balance × 1.10 − 0.3 PC > balance for any non-trivial balance. See
260
- // preflight.ts:215.
261
- const SWAP_BUFFER_NUM = BigInt(22);
262
- const SWAP_BUFFER_DEN = BigInt(10);
263
- const BALANCE_FALLBACK_DIVISOR = BigInt(10); // 10% of balance as fallback
264
- const GAS_RESERVE = BigInt(3e18); // 3 UPC reserve for tx overhead
265
- try {
266
- // Read WPC, factory, and defaultFeeTier in parallel
267
- const [wpcAddress, factoryAddress, feeTier] = yield Promise.all([
268
- ctx.pushClient.readContract({
269
- address: universalCoreAddress,
270
- abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
271
- functionName: 'WPC',
272
- args: [],
273
- }),
274
- ctx.pushClient.readContract({
275
- address: universalCoreAddress,
276
- abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
277
- functionName: 'uniswapV3Factory',
278
- args: [],
279
- }),
280
- ctx.pushClient.readContract({
281
- address: universalCoreAddress,
282
- abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
283
- functionName: 'defaultFeeTier',
284
- args: [gasToken],
285
- }),
286
- ]);
287
- if (!feeTier) {
288
- (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — no fee tier for gasToken, using balance fallback`);
289
- return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
290
- }
291
- const pushChain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
292
- 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;
293
- if (quoterAddress && !quoterAddress.startsWith('0xTBD')) {
294
- try {
295
- const quote = yield ctx.pushClient.readContract({
296
- address: quoterAddress,
297
- abi: UNISWAP_V3_QUOTER_EXACT_OUTPUT_ABI,
298
- functionName: 'quoteExactOutputSingle',
299
- args: [
300
- {
301
- tokenIn: wpcAddress,
302
- tokenOut: gasToken,
303
- amount: gasFee,
304
- fee: feeTier,
305
- sqrtPriceLimitX96: BigInt(0),
306
- },
307
- ],
308
- });
309
- const exactWpcNeeded = quote[0];
310
- const result = (exactWpcNeeded * SWAP_BUFFER_NUM) / SWAP_BUFFER_DEN;
311
- (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — exactOutput quoter=${quoterAddress}, ` +
312
- `wpcNeeded=${exactWpcNeeded}, withBuffer(2.2x)=${result}`);
313
- return capSwapEstimate(result, accountBalance, GAS_RESERVE, exactWpcNeeded);
314
- }
315
- catch (quoteErr) {
316
- (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — exactOutput quote failed: ${quoteErr instanceof Error ? quoteErr.message : String(quoteErr)}, falling back to slot0 price`);
317
- }
318
- }
319
- // Get pool address from factory
320
- const poolAddress = yield ctx.pushClient.readContract({
321
- address: factoryAddress,
322
- abi: UNISWAP_V3_FACTORY_ABI,
323
- functionName: 'getPool',
324
- args: [wpcAddress, gasToken, feeTier],
325
- });
326
- if (poolAddress === ZERO_ADDR) {
327
- (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — pool not found, using balance fallback`);
328
- return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
329
- }
330
- // Read slot0 for current price
331
- const slot0 = yield ctx.pushClient.readContract({
332
- address: poolAddress,
333
- abi: UNISWAP_V3_POOL_SLOT0_ABI,
334
- functionName: 'slot0',
242
+ async function estimateNativeValueForSwap(ctx, universalCoreAddress, gasToken, gasFee, accountBalance) {
243
+ // 2.2x safety buffer applied to the pool quote; excess is refunded by
244
+ // swapAndBurnGas. Composed of a 2x pool-slippage cushion plus 10%
245
+ // headroom that used to live in the R2 route-handler callers (×110/100
246
+ // after this function returned). Folded into one place here so the cap
247
+ // branch below correctly bounds the FINAL inflated value — the previous
248
+ // arrangement (outer ×1.10 on top of an inner cap that returned
249
+ // `balance - GAS_RESERVE`) caused a deterministic preflight failure
250
+ // whenever the cap fired: required = 1.10 × (balance − 3 PC) + 3 PC ≈
251
+ // balance × 1.10 − 0.3 PC > balance for any non-trivial balance. See
252
+ // preflight.ts:215.
253
+ const SWAP_BUFFER_NUM = BigInt(22);
254
+ const SWAP_BUFFER_DEN = BigInt(10);
255
+ const BALANCE_FALLBACK_DIVISOR = BigInt(10); // 10% of balance as fallback
256
+ const GAS_RESERVE = BigInt(3e18); // 3 UPC reserve for tx overhead
257
+ try {
258
+ // Read WPC, factory, and defaultFeeTier in parallel
259
+ const [wpcAddress, factoryAddress, feeTier] = await Promise.all([
260
+ ctx.pushClient.readContract({
261
+ address: universalCoreAddress,
262
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
263
+ functionName: 'WPC',
335
264
  args: [],
336
- });
337
- const sqrtPriceX96 = slot0[0];
338
- if (!sqrtPriceX96 || sqrtPriceX96 === BigInt(0)) {
339
- (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — pool not initialized, using balance fallback`);
340
- return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
341
- }
342
- // price (token1/token0 in raw units) = (sqrtPriceX96)² / 2¹⁹²
343
- const Q192 = BigInt(1) << BigInt(192);
344
- const priceNum = sqrtPriceX96 * sqrtPriceX96; // sqrtPrice² in Q192
345
- // Uniswap V3 sorts tokens: token0 < token1 by address
346
- const isGasTokenToken0 = gasToken.toLowerCase() < wpcAddress.toLowerCase();
347
- let wpcNeeded;
348
- if (isGasTokenToken0) {
349
- // price = WPC_per_gasToken → wpcNeeded = gasFee * price
350
- wpcNeeded = (gasFee * priceNum) / Q192;
265
+ }),
266
+ ctx.pushClient.readContract({
267
+ address: universalCoreAddress,
268
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
269
+ functionName: 'uniswapV3Factory',
270
+ args: [],
271
+ }),
272
+ ctx.pushClient.readContract({
273
+ address: universalCoreAddress,
274
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
275
+ functionName: 'defaultFeeTier',
276
+ args: [gasToken],
277
+ }),
278
+ ]);
279
+ if (!feeTier) {
280
+ (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — no fee tier for gasToken, using balance fallback`);
281
+ return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
282
+ }
283
+ const pushChain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
284
+ const quoterAddress = chain_1.CHAIN_INFO[pushChain]?.dex?.uniV3QuoterV2;
285
+ if (quoterAddress && !quoterAddress.startsWith('0xTBD')) {
286
+ try {
287
+ const quote = await ctx.pushClient.readContract({
288
+ address: quoterAddress,
289
+ abi: UNISWAP_V3_QUOTER_EXACT_OUTPUT_ABI,
290
+ functionName: 'quoteExactOutputSingle',
291
+ args: [
292
+ {
293
+ tokenIn: wpcAddress,
294
+ tokenOut: gasToken,
295
+ amount: gasFee,
296
+ fee: feeTier,
297
+ sqrtPriceLimitX96: BigInt(0),
298
+ },
299
+ ],
300
+ });
301
+ const exactWpcNeeded = quote[0];
302
+ const result = (exactWpcNeeded * SWAP_BUFFER_NUM) / SWAP_BUFFER_DEN;
303
+ (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — exactOutput quoter=${quoterAddress}, ` +
304
+ `wpcNeeded=${exactWpcNeeded}, withBuffer(2.2x)=${result}`);
305
+ return capSwapEstimate(result, accountBalance, GAS_RESERVE, exactWpcNeeded);
351
306
  }
352
- else {
353
- // price = gasToken_per_WPC → wpcNeeded = gasFee / price
354
- wpcNeeded = (gasFee * Q192) / priceNum;
307
+ catch (quoteErr) {
308
+ (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — exactOutput quote failed: ${quoteErr instanceof Error ? quoteErr.message : String(quoteErr)}, falling back to slot0 price`);
355
309
  }
356
- const result = (wpcNeeded * SWAP_BUFFER_NUM) / SWAP_BUFFER_DEN;
357
- (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — pool=${poolAddress}, sqrtPriceX96=${sqrtPriceX96}, ` +
358
- `wpcNeeded=${wpcNeeded}, withBuffer(2.2x)=${result}`);
359
- return capSwapEstimate(result, accountBalance, GAS_RESERVE, wpcNeeded);
360
310
  }
361
- catch (err) {
362
- (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — failed: ${err instanceof Error ? err.message : String(err)}, using balance fallback`);
311
+ // Get pool address from factory
312
+ const poolAddress = await ctx.pushClient.readContract({
313
+ address: factoryAddress,
314
+ abi: UNISWAP_V3_FACTORY_ABI,
315
+ functionName: 'getPool',
316
+ args: [wpcAddress, gasToken, feeTier],
317
+ });
318
+ if (poolAddress === ZERO_ADDR) {
319
+ (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — pool not found, using balance fallback`);
363
320
  return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
364
321
  }
365
- });
322
+ // Read slot0 for current price
323
+ const slot0 = await ctx.pushClient.readContract({
324
+ address: poolAddress,
325
+ abi: UNISWAP_V3_POOL_SLOT0_ABI,
326
+ functionName: 'slot0',
327
+ args: [],
328
+ });
329
+ const sqrtPriceX96 = slot0[0];
330
+ if (!sqrtPriceX96 || sqrtPriceX96 === BigInt(0)) {
331
+ (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — pool not initialized, using balance fallback`);
332
+ return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
333
+ }
334
+ // price (token1/token0 in raw units) = (sqrtPriceX96)² / 2¹⁹²
335
+ const Q192 = BigInt(1) << BigInt(192);
336
+ const priceNum = sqrtPriceX96 * sqrtPriceX96; // sqrtPrice² in Q192
337
+ // Uniswap V3 sorts tokens: token0 < token1 by address
338
+ const isGasTokenToken0 = gasToken.toLowerCase() < wpcAddress.toLowerCase();
339
+ let wpcNeeded;
340
+ if (isGasTokenToken0) {
341
+ // price = WPC_per_gasToken → wpcNeeded = gasFee * price
342
+ wpcNeeded = (gasFee * priceNum) / Q192;
343
+ }
344
+ else {
345
+ // price = gasToken_per_WPC → wpcNeeded = gasFee / price
346
+ wpcNeeded = (gasFee * Q192) / priceNum;
347
+ }
348
+ const result = (wpcNeeded * SWAP_BUFFER_NUM) / SWAP_BUFFER_DEN;
349
+ (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — pool=${poolAddress}, sqrtPriceX96=${sqrtPriceX96}, ` +
350
+ `wpcNeeded=${wpcNeeded}, withBuffer(2.2x)=${result}`);
351
+ return capSwapEstimate(result, accountBalance, GAS_RESERVE, wpcNeeded);
352
+ }
353
+ catch (err) {
354
+ (0, context_1.printLog)(ctx, `estimateNativeValueForSwap — failed: ${err instanceof Error ? err.message : String(err)}, using balance fallback`);
355
+ return balanceFallback(accountBalance, BALANCE_FALLBACK_DIVISOR, GAS_RESERVE);
356
+ }
366
357
  }
367
358
  /**
368
359
  * Bound the buffered swap estimate by the UEA's affordable PC.
@@ -400,169 +391,161 @@ function balanceFallback(balance, divisor, reserve) {
400
391
  // ============================================================================
401
392
  // Rescue Gas Fee Query
402
393
  // ============================================================================
403
- function queryRescueGasFee(ctx, prc20Token, destinationChain) {
404
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
405
- const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
406
- (0, context_1.printLog)(ctx, `queryRescueGasFee — inputs: gateway=${gatewayPcAddress}, prc20Token=${prc20Token}`);
407
- let universalCoreAddress;
408
- try {
409
- universalCoreAddress = yield ctx.pushClient.readContract({
410
- address: gatewayPcAddress,
411
- abi: abi_1.UNIVERSAL_GATEWAY_PC,
412
- functionName: 'universalCore',
413
- args: [],
414
- });
415
- (0, context_1.printLog)(ctx, `queryRescueGasFee — universalCore resolved to: ${universalCoreAddress}`);
416
- }
417
- catch (err) {
418
- (0, context_1.printLog)(ctx, `queryRescueGasFee — FAILED to read universalCore: ${err instanceof Error ? err.message : String(err)}`);
419
- throw err;
420
- }
421
- let gasToken;
422
- let gasFee;
423
- let rescueGasLimit;
424
- let gasPrice;
394
+ async function queryRescueGasFee(ctx, prc20Token, destinationChain) {
395
+ const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
396
+ (0, context_1.printLog)(ctx, `queryRescueGasFee — inputs: gateway=${gatewayPcAddress}, prc20Token=${prc20Token}`);
397
+ let universalCoreAddress;
398
+ try {
399
+ universalCoreAddress = await ctx.pushClient.readContract({
400
+ address: gatewayPcAddress,
401
+ abi: abi_1.UNIVERSAL_GATEWAY_PC,
402
+ functionName: 'universalCore',
403
+ args: [],
404
+ });
405
+ (0, context_1.printLog)(ctx, `queryRescueGasFee — universalCore resolved to: ${universalCoreAddress}`);
406
+ }
407
+ catch (err) {
408
+ (0, context_1.printLog)(ctx, `queryRescueGasFee — FAILED to read universalCore: ${err instanceof Error ? err.message : String(err)}`);
409
+ throw err;
410
+ }
411
+ let gasToken;
412
+ let gasFee;
413
+ let rescueGasLimit;
414
+ let gasPrice;
415
+ try {
416
+ const result = await ctx.pushClient.readContract({
417
+ address: universalCoreAddress,
418
+ abi: abi_1.UNIVERSAL_CORE_EVM,
419
+ functionName: 'getRescueFundsGasLimit',
420
+ args: [prc20Token],
421
+ });
422
+ gasToken = result[0];
423
+ gasFee = result[1];
424
+ rescueGasLimit = result[2];
425
+ gasPrice = result[3];
426
+ (0, context_1.printLog)(ctx, `queryRescueGasFee — success: gasToken=${gasToken}, gasFee=${gasFee}, rescueGasLimit=${rescueGasLimit}, gasPrice=${gasPrice}`);
427
+ }
428
+ catch (err) {
429
+ (0, context_1.printLog)(ctx, `queryRescueGasFee — FAILED: ${err instanceof Error ? err.message : String(err)}`);
430
+ throw err;
431
+ }
432
+ let nativeValueForGas;
433
+ let sizing;
434
+ if (destinationChain !== undefined) {
425
435
  try {
426
- const result = yield ctx.pushClient.readContract({
427
- address: universalCoreAddress,
428
- abi: abi_1.UNIVERSAL_CORE_EVM,
429
- functionName: 'getRescueFundsGasLimit',
430
- args: [prc20Token],
436
+ sizing = await (0, gas_usd_sizer_1.sizeOutboundGas)(ctx, {
437
+ gasFee,
438
+ originChain: ctx.universalSigner.account.chain,
439
+ destinationChain,
431
440
  });
432
- gasToken = result[0];
433
- gasFee = result[1];
434
- rescueGasLimit = result[2];
435
- gasPrice = result[3];
436
- (0, context_1.printLog)(ctx, `queryRescueGasFee — success: gasToken=${gasToken}, gasFee=${gasFee}, rescueGasLimit=${rescueGasLimit}, gasPrice=${gasPrice}`);
441
+ nativeValueForGas = sizing.gasLegNativePc;
442
+ (0, context_1.printLog)(ctx, `queryRescueGasFee — sizer: category=${sizing.category}, gasUsd=${sizing.gasUsd}, nativeValueForGas=${nativeValueForGas}`);
437
443
  }
438
444
  catch (err) {
439
- (0, context_1.printLog)(ctx, `queryRescueGasFee — FAILED: ${err instanceof Error ? err.message : String(err)}`);
440
- throw err;
441
- }
442
- let nativeValueForGas;
443
- let sizing;
444
- if (destinationChain !== undefined) {
445
- try {
446
- sizing = yield (0, gas_usd_sizer_1.sizeOutboundGas)(ctx, {
447
- gasFee,
448
- originChain: ctx.universalSigner.account.chain,
449
- destinationChain,
450
- });
451
- nativeValueForGas = sizing.gasLegNativePc;
452
- (0, context_1.printLog)(ctx, `queryRescueGasFee — sizer: category=${sizing.category}, gasUsd=${sizing.gasUsd}, nativeValueForGas=${nativeValueForGas}`);
453
- }
454
- catch (err) {
455
- (0, context_1.printLog)(ctx, `queryRescueGasFee — sizer failed (${err instanceof Error ? err.message : String(err)}); falling back to 1M buffer`);
456
- nativeValueForGas = gasFee * GAS_FEE_BUFFER_MULTIPLIER;
457
- }
458
- }
459
- else {
445
+ (0, context_1.printLog)(ctx, `queryRescueGasFee — sizer failed (${err instanceof Error ? err.message : String(err)}); falling back to 1M buffer`);
460
446
  nativeValueForGas = gasFee * GAS_FEE_BUFFER_MULTIPLIER;
461
- (0, context_1.printLog)(ctx, `queryRescueGasFee — no destinationChain provided; legacy 1M buffer: nativeValueForGas=${nativeValueForGas}`);
462
447
  }
463
- return { gasToken, gasFee, rescueGasLimit, gasPrice, nativeValueForGas, sizing };
464
- });
448
+ }
449
+ else {
450
+ nativeValueForGas = gasFee * GAS_FEE_BUFFER_MULTIPLIER;
451
+ (0, context_1.printLog)(ctx, `queryRescueGasFee — no destinationChain provided; legacy 1M buffer: nativeValueForGas=${nativeValueForGas}`);
452
+ }
453
+ return { gasToken, gasFee, rescueGasLimit, gasPrice, nativeValueForGas, sizing };
465
454
  }
466
455
  // ============================================================================
467
456
  // Native Amount Calculation for Deposit
468
457
  // ============================================================================
469
- function calculateNativeAmountForDeposit(ctx, chain, requiredFunds, ueaBalance,
458
+ async function calculateNativeAmountForDeposit(ctx, chain, requiredFunds, ueaBalance,
470
459
  // When false, suppress the SEND-TX-103-03-04 ("Prepaid Deposit Estimated")
471
460
  // progress hook so the caller can emit the full 103-03 sizing sequence
472
461
  // (parent + Case A/B/C + terminal) AFTER 103-01/103-02, matching the
473
462
  // funds-payload path ordering. The deposit math is unaffected.
474
463
  opts) {
475
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
476
- var _a, _b;
477
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_102_01);
478
- const oneUsd = utils_1.Utils.helpers.parseUnits('1', 8);
479
- const maxUsd = utils_1.Utils.helpers.parseUnits('1000', 8);
480
- const deficit = requiredFunds > ueaBalance ? requiredFunds - ueaBalance : BigInt(0);
481
- let depositUsd = deficit > BigInt(0) ? ctx.pushClient.pushToUSDC(deficit) : oneUsd;
482
- if (depositUsd < oneUsd)
483
- depositUsd = oneUsd;
484
- if (depositUsd > maxUsd)
485
- throw new Error('Deposit value exceeds max $1000 worth of native token');
486
- if (chain_1.CHAIN_INFO[chain].vm === enums_1.VM.SVM) {
487
- const svmClient = new svm_client_1.SvmClient({
488
- rpcUrls: ctx.rpcUrls[enums_1.CHAIN.SOLANA_DEVNET] ||
489
- chain_1.CHAIN_INFO[enums_1.CHAIN.SOLANA_DEVNET].defaultRPC,
464
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_102_01);
465
+ const oneUsd = utils_1.Utils.helpers.parseUnits('1', 8);
466
+ const maxUsd = utils_1.Utils.helpers.parseUnits('1000', 8);
467
+ const deficit = requiredFunds > ueaBalance ? requiredFunds - ueaBalance : BigInt(0);
468
+ let depositUsd = deficit > BigInt(0) ? ctx.pushClient.pushToUSDC(deficit) : oneUsd;
469
+ if (depositUsd < oneUsd)
470
+ depositUsd = oneUsd;
471
+ if (depositUsd > maxUsd)
472
+ throw new Error('Deposit value exceeds max $1000 worth of native token');
473
+ if (chain_1.CHAIN_INFO[chain].vm === enums_1.VM.SVM) {
474
+ const svmClient = new svm_client_1.SvmClient({
475
+ rpcUrls: ctx.rpcUrls[enums_1.CHAIN.SOLANA_DEVNET] ||
476
+ chain_1.CHAIN_INFO[enums_1.CHAIN.SOLANA_DEVNET].defaultRPC,
477
+ });
478
+ const programId = new web3_js_1.PublicKey(abi_1.SVM_GATEWAY_IDL.address);
479
+ const [configPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('config')], programId);
480
+ try {
481
+ const cfg = await svmClient.readContract({
482
+ abi: abi_1.SVM_GATEWAY_IDL,
483
+ address: abi_1.SVM_GATEWAY_IDL.address,
484
+ functionName: 'config',
485
+ args: [configPda.toBase58()],
490
486
  });
491
- const programId = new web3_js_1.PublicKey(abi_1.SVM_GATEWAY_IDL.address);
492
- const [configPda] = web3_js_1.PublicKey.findProgramAddressSync([(0, viem_1.stringToBytes)('config')], programId);
493
- try {
494
- const cfg = yield svmClient.readContract({
495
- abi: abi_1.SVM_GATEWAY_IDL,
496
- address: abi_1.SVM_GATEWAY_IDL.address,
497
- functionName: 'config',
498
- args: [configPda.toBase58()],
499
- });
500
- const minField = (_a = cfg.minCapUniversalTxUsd) !== null && _a !== void 0 ? _a : cfg.min_cap_universal_tx_usd;
501
- const maxField = (_b = cfg.maxCapUniversalTxUsd) !== null && _b !== void 0 ? _b : cfg.max_cap_universal_tx_usd;
502
- const minCapUsd = BigInt(minField.toString());
503
- const maxCapUsd = BigInt(maxField.toString());
504
- if (depositUsd < minCapUsd)
505
- depositUsd = minCapUsd;
506
- const withMargin = (minCapUsd * BigInt(12)) / BigInt(10);
507
- if (depositUsd < withMargin)
508
- depositUsd = withMargin;
509
- if (depositUsd > maxCapUsd)
510
- depositUsd = maxCapUsd;
511
- }
512
- catch (_c) {
513
- // best-effort
514
- }
487
+ const minField = cfg.minCapUniversalTxUsd ?? cfg.min_cap_universal_tx_usd;
488
+ const maxField = cfg.maxCapUniversalTxUsd ?? cfg.max_cap_universal_tx_usd;
489
+ const minCapUsd = BigInt(minField.toString());
490
+ const maxCapUsd = BigInt(maxField.toString());
491
+ if (depositUsd < minCapUsd)
492
+ depositUsd = minCapUsd;
493
+ const withMargin = (minCapUsd * BigInt(12)) / BigInt(10);
494
+ if (depositUsd < withMargin)
495
+ depositUsd = withMargin;
496
+ if (depositUsd > maxCapUsd)
497
+ depositUsd = maxCapUsd;
515
498
  }
516
- const nativeTokenUsdPrice = yield new price_fetch_1.PriceFetch(ctx.rpcUrls).getPrice(chain);
517
- const nativeDecimals = chain_1.CHAIN_INFO[chain].vm === enums_1.VM.SVM ? 9 : 18;
518
- const oneNativeUnit = utils_1.Utils.helpers.parseUnits('1', nativeDecimals);
519
- let nativeAmount = (depositUsd * oneNativeUnit + (nativeTokenUsdPrice - BigInt(1))) /
520
- nativeTokenUsdPrice;
521
- nativeAmount = nativeAmount + BigInt(1);
522
- if ((opts === null || opts === void 0 ? void 0 : opts.emitDepositEstimated) !== false) {
523
- (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_103_03_04, nativeAmount, depositUsd, chain);
499
+ catch {
500
+ // best-effort
524
501
  }
525
- return nativeAmount;
526
- });
502
+ }
503
+ const nativeTokenUsdPrice = await new price_fetch_1.PriceFetch(ctx.rpcUrls).getPrice(chain);
504
+ const nativeDecimals = chain_1.CHAIN_INFO[chain].vm === enums_1.VM.SVM ? 9 : 18;
505
+ const oneNativeUnit = utils_1.Utils.helpers.parseUnits('1', nativeDecimals);
506
+ let nativeAmount = (depositUsd * oneNativeUnit + (nativeTokenUsdPrice - BigInt(1))) /
507
+ nativeTokenUsdPrice;
508
+ nativeAmount = nativeAmount + BigInt(1);
509
+ if (opts?.emitDepositEstimated !== false) {
510
+ (0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_103_03_04, nativeAmount, depositUsd, chain);
511
+ }
512
+ return nativeAmount;
527
513
  }
528
514
  // ============================================================================
529
515
  // ERC-20 Gas Amount from Exact Output Quote
530
516
  // ============================================================================
531
- function calculateGasAmountFromAmountOutMinETH(ctx, gasTokenAddress, amountOutMinETH, quoteExactOutputFn) {
532
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
533
- var _a, _b, _c;
534
- const originChain = ctx.universalSigner.account.chain;
535
- if (originChain !== enums_1.CHAIN.ETHEREUM_SEPOLIA &&
536
- originChain !== enums_1.CHAIN.ARBITRUM_SEPOLIA &&
537
- originChain !== enums_1.CHAIN.BASE_SEPOLIA) {
538
- throw new Error('Gas payment in ERC-20 is supported only on Ethereum Sepolia, Arbitrum Sepolia, and Base Sepolia for now');
539
- }
540
- const WETH = (_a = chain_1.CHAIN_INFO[originChain].dex) === null || _a === void 0 ? void 0 : _a.weth;
541
- if (!WETH)
542
- throw new Error('WETH address not configured for this chain');
543
- let gasAmount;
544
- if (gasTokenAddress.toLowerCase() === WETH.toLowerCase()) {
545
- gasAmount = BigInt(amountOutMinETH);
546
- }
547
- else {
548
- const fromList = (_b = tokens_1.PAYABLE_TOKENS[originChain]) !== null && _b !== void 0 ? _b : [];
549
- const fromToken = fromList.find((t) => (t.address || '').toLowerCase() === gasTokenAddress.toLowerCase());
550
- const toList = ((_c = tokens_1.MOVEABLE_TOKENS[originChain]) !== null && _c !== void 0 ? _c : []);
551
- const toToken = toList.find((t) => t.symbol === 'WETH' ||
552
- (t.address || '').toLowerCase() === (WETH || '').toLowerCase());
553
- if (!fromToken || !toToken) {
554
- throw new Error('Token not supported for quoting');
555
- }
556
- const targetOut = BigInt(amountOutMinETH);
557
- const exactOutQuote = yield quoteExactOutputFn(targetOut, {
558
- from: fromToken,
559
- to: toToken,
560
- });
561
- const requiredIn = BigInt(exactOutQuote.amountIn);
562
- gasAmount = (requiredIn * BigInt(101)) / BigInt(100);
517
+ async function calculateGasAmountFromAmountOutMinETH(ctx, gasTokenAddress, amountOutMinETH, quoteExactOutputFn) {
518
+ const originChain = ctx.universalSigner.account.chain;
519
+ if (originChain !== enums_1.CHAIN.ETHEREUM_SEPOLIA &&
520
+ originChain !== enums_1.CHAIN.ARBITRUM_SEPOLIA &&
521
+ originChain !== enums_1.CHAIN.BASE_SEPOLIA) {
522
+ throw new Error('Gas payment in ERC-20 is supported only on Ethereum Sepolia, Arbitrum Sepolia, and Base Sepolia for now');
523
+ }
524
+ const WETH = chain_1.CHAIN_INFO[originChain].dex?.weth;
525
+ if (!WETH)
526
+ throw new Error('WETH address not configured for this chain');
527
+ let gasAmount;
528
+ if (gasTokenAddress.toLowerCase() === WETH.toLowerCase()) {
529
+ gasAmount = BigInt(amountOutMinETH);
530
+ }
531
+ else {
532
+ const fromList = tokens_1.PAYABLE_TOKENS[originChain] ?? [];
533
+ const fromToken = fromList.find((t) => (t.address || '').toLowerCase() === gasTokenAddress.toLowerCase());
534
+ const toList = (tokens_1.MOVEABLE_TOKENS[originChain] ?? []);
535
+ const toToken = toList.find((t) => t.symbol === 'WETH' ||
536
+ (t.address || '').toLowerCase() === (WETH || '').toLowerCase());
537
+ if (!fromToken || !toToken) {
538
+ throw new Error('Token not supported for quoting');
563
539
  }
564
- return { gasAmount };
565
- });
540
+ const targetOut = BigInt(amountOutMinETH);
541
+ const exactOutQuote = await quoteExactOutputFn(targetOut, {
542
+ from: fromToken,
543
+ to: toToken,
544
+ });
545
+ const requiredIn = BigInt(exactOutQuote.amountIn);
546
+ gasAmount = (requiredIn * BigInt(101)) / BigInt(100);
547
+ }
548
+ return { gasAmount };
566
549
  }
567
550
  // ============================================================================
568
551
  // Estimate UPC deposit from locked ETH via Uniswap V3 quote
@@ -575,87 +558,84 @@ function calculateGasAmountFromAmountOutMinETH(ctx, gasTokenAddress, amountOutMi
575
558
  * Queries the same Uniswap V3 QuoterV2 the chain uses in execute_inbound_gas.go.
576
559
  * Returns 0 on any failure (caller should fall back to other logic).
577
560
  */
578
- function estimateDepositFromLockedNative(ctx, nativeAmountForLocker, prc20Token) {
579
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
580
- var _a, _b;
581
- try {
582
- const pushChain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
583
- 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;
584
- if (!quoterAddress || quoterAddress.startsWith('0xTBD'))
585
- return BigInt(0);
586
- // Get UniversalCore → WPC address + fee tier (reuses existing ABI)
587
- const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
588
- const universalCoreAddress = yield ctx.pushClient.readContract({
589
- address: gatewayPcAddress,
590
- abi: abi_1.UNIVERSAL_GATEWAY_PC,
591
- functionName: 'universalCore',
561
+ async function estimateDepositFromLockedNative(ctx, nativeAmountForLocker, prc20Token) {
562
+ try {
563
+ const pushChain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
564
+ const quoterAddress = chain_1.CHAIN_INFO[pushChain]?.dex?.uniV3QuoterV2;
565
+ if (!quoterAddress || quoterAddress.startsWith('0xTBD'))
566
+ return BigInt(0);
567
+ // Get UniversalCore → WPC address + fee tier (reuses existing ABI)
568
+ const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
569
+ const universalCoreAddress = await ctx.pushClient.readContract({
570
+ address: gatewayPcAddress,
571
+ abi: abi_1.UNIVERSAL_GATEWAY_PC,
572
+ functionName: 'universalCore',
573
+ args: [],
574
+ });
575
+ const [wpcAddress, feeTier] = await Promise.all([
576
+ ctx.pushClient.readContract({
577
+ address: universalCoreAddress,
578
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
579
+ functionName: 'WPC',
592
580
  args: [],
593
- });
594
- const [wpcAddress, feeTier] = yield Promise.all([
595
- ctx.pushClient.readContract({
596
- address: universalCoreAddress,
597
- abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
598
- functionName: 'WPC',
599
- args: [],
600
- }),
601
- ctx.pushClient.readContract({
602
- address: universalCoreAddress,
603
- abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
604
- functionName: 'defaultFeeTier',
605
- args: [prc20Token],
606
- }),
607
- ]);
608
- if (!feeTier || !wpcAddress)
609
- return BigInt(0);
610
- // QuoterV2.quoteExactInputSingle — same call the chain relay makes
611
- const QUOTER_ABI = [
612
- {
613
- type: 'function',
614
- name: 'quoteExactInputSingle',
615
- inputs: [
616
- {
617
- type: 'tuple',
618
- components: [
619
- { name: 'tokenIn', type: 'address' },
620
- { name: 'tokenOut', type: 'address' },
621
- { name: 'amountIn', type: 'uint256' },
622
- { name: 'fee', type: 'uint24' },
623
- { name: 'sqrtPriceLimitX96', type: 'uint160' },
624
- ],
625
- },
626
- ],
627
- outputs: [
628
- { name: 'amountOut', type: 'uint256' },
629
- { name: 'sqrtPriceX96After', type: 'uint160' },
630
- { name: 'initializedTicksCrossed', type: 'uint32' },
631
- { name: 'gasEstimate', type: 'uint256' },
632
- ],
633
- stateMutability: 'view',
634
- },
635
- ];
636
- const result = yield ctx.pushClient.readContract({
637
- address: quoterAddress,
638
- abi: QUOTER_ABI,
639
- functionName: 'quoteExactInputSingle',
640
- args: [
581
+ }),
582
+ ctx.pushClient.readContract({
583
+ address: universalCoreAddress,
584
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
585
+ functionName: 'defaultFeeTier',
586
+ args: [prc20Token],
587
+ }),
588
+ ]);
589
+ if (!feeTier || !wpcAddress)
590
+ return BigInt(0);
591
+ // QuoterV2.quoteExactInputSingle — same call the chain relay makes
592
+ const QUOTER_ABI = [
593
+ {
594
+ type: 'function',
595
+ name: 'quoteExactInputSingle',
596
+ inputs: [
641
597
  {
642
- tokenIn: prc20Token,
643
- tokenOut: wpcAddress,
644
- amountIn: nativeAmountForLocker,
645
- fee: feeTier,
646
- sqrtPriceLimitX96: BigInt(0),
598
+ type: 'tuple',
599
+ components: [
600
+ { name: 'tokenIn', type: 'address' },
601
+ { name: 'tokenOut', type: 'address' },
602
+ { name: 'amountIn', type: 'uint256' },
603
+ { name: 'fee', type: 'uint24' },
604
+ { name: 'sqrtPriceLimitX96', type: 'uint160' },
605
+ ],
647
606
  },
648
607
  ],
649
- });
650
- const amountOut = result[0];
651
- (0, context_1.printLog)(ctx, `estimateDepositFromLockedNative — quote: ${nativeAmountForLocker.toString()} pETH → ${amountOut.toString()} WPC (fee tier: ${feeTier})`);
652
- return amountOut;
653
- }
654
- catch (err) {
655
- (0, context_1.printLog)(ctx, `estimateDepositFromLockedNative — failed: ${err instanceof Error ? err.message : String(err)}`);
656
- return BigInt(0);
657
- }
658
- });
608
+ outputs: [
609
+ { name: 'amountOut', type: 'uint256' },
610
+ { name: 'sqrtPriceX96After', type: 'uint160' },
611
+ { name: 'initializedTicksCrossed', type: 'uint32' },
612
+ { name: 'gasEstimate', type: 'uint256' },
613
+ ],
614
+ stateMutability: 'view',
615
+ },
616
+ ];
617
+ const result = await ctx.pushClient.readContract({
618
+ address: quoterAddress,
619
+ abi: QUOTER_ABI,
620
+ functionName: 'quoteExactInputSingle',
621
+ args: [
622
+ {
623
+ tokenIn: prc20Token,
624
+ tokenOut: wpcAddress,
625
+ amountIn: nativeAmountForLocker,
626
+ fee: feeTier,
627
+ sqrtPriceLimitX96: BigInt(0),
628
+ },
629
+ ],
630
+ });
631
+ const amountOut = result[0];
632
+ (0, context_1.printLog)(ctx, `estimateDepositFromLockedNative — quote: ${nativeAmountForLocker.toString()} pETH → ${amountOut.toString()} WPC (fee tier: ${feeTier})`);
633
+ return amountOut;
634
+ }
635
+ catch (err) {
636
+ (0, context_1.printLog)(ctx, `estimateDepositFromLockedNative — failed: ${err instanceof Error ? err.message : String(err)}`);
637
+ return BigInt(0);
638
+ }
659
639
  }
660
640
  /**
661
641
  * Inverse of estimateDepositFromLockedNative: given a desired WPC output,
@@ -666,86 +646,83 @@ function estimateDepositFromLockedNative(ctx, nativeAmountForLocker, prc20Token)
666
646
  * of the fixed $0.10/PC SDK rate. Returns 0 on any failure (caller should
667
647
  * fall back to the fixed-rate sizing).
668
648
  */
669
- function estimateNativeForDesiredDeposit(ctx, desiredWpc, prc20Token) {
670
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
671
- var _a, _b;
672
- try {
673
- if (desiredWpc <= BigInt(0))
674
- return BigInt(0);
675
- const pushChain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
676
- 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;
677
- if (!quoterAddress || quoterAddress.startsWith('0xTBD'))
678
- return BigInt(0);
679
- const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
680
- const universalCoreAddress = yield ctx.pushClient.readContract({
681
- address: gatewayPcAddress,
682
- abi: abi_1.UNIVERSAL_GATEWAY_PC,
683
- functionName: 'universalCore',
649
+ async function estimateNativeForDesiredDeposit(ctx, desiredWpc, prc20Token) {
650
+ try {
651
+ if (desiredWpc <= BigInt(0))
652
+ return BigInt(0);
653
+ const pushChain = (0, helpers_1.getPushChainForNetwork)(ctx.pushNetwork);
654
+ const quoterAddress = chain_1.CHAIN_INFO[pushChain]?.dex?.uniV3QuoterV2;
655
+ if (!quoterAddress || quoterAddress.startsWith('0xTBD'))
656
+ return BigInt(0);
657
+ const gatewayPcAddress = (0, helpers_1.getUniversalGatewayPCAddress)();
658
+ const universalCoreAddress = await ctx.pushClient.readContract({
659
+ address: gatewayPcAddress,
660
+ abi: abi_1.UNIVERSAL_GATEWAY_PC,
661
+ functionName: 'universalCore',
662
+ args: [],
663
+ });
664
+ const [wpcAddress, feeTier] = await Promise.all([
665
+ ctx.pushClient.readContract({
666
+ address: universalCoreAddress,
667
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
668
+ functionName: 'WPC',
684
669
  args: [],
685
- });
686
- const [wpcAddress, feeTier] = yield Promise.all([
687
- ctx.pushClient.readContract({
688
- address: universalCoreAddress,
689
- abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
690
- functionName: 'WPC',
691
- args: [],
692
- }),
693
- ctx.pushClient.readContract({
694
- address: universalCoreAddress,
695
- abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
696
- functionName: 'defaultFeeTier',
697
- args: [prc20Token],
698
- }),
699
- ]);
700
- if (!feeTier || !wpcAddress)
701
- return BigInt(0);
702
- const QUOTER_ABI = [
703
- {
704
- type: 'function',
705
- name: 'quoteExactOutputSingle',
706
- inputs: [
707
- {
708
- type: 'tuple',
709
- components: [
710
- { name: 'tokenIn', type: 'address' },
711
- { name: 'tokenOut', type: 'address' },
712
- { name: 'amount', type: 'uint256' },
713
- { name: 'fee', type: 'uint24' },
714
- { name: 'sqrtPriceLimitX96', type: 'uint160' },
715
- ],
716
- },
717
- ],
718
- outputs: [
719
- { name: 'amountIn', type: 'uint256' },
720
- { name: 'sqrtPriceX96After', type: 'uint160' },
721
- { name: 'initializedTicksCrossed', type: 'uint32' },
722
- { name: 'gasEstimate', type: 'uint256' },
723
- ],
724
- stateMutability: 'view',
725
- },
726
- ];
727
- const result = yield ctx.pushClient.readContract({
728
- address: quoterAddress,
729
- abi: QUOTER_ABI,
730
- functionName: 'quoteExactOutputSingle',
731
- args: [
670
+ }),
671
+ ctx.pushClient.readContract({
672
+ address: universalCoreAddress,
673
+ abi: UNIVERSAL_CORE_SWAP_HELPERS_ABI,
674
+ functionName: 'defaultFeeTier',
675
+ args: [prc20Token],
676
+ }),
677
+ ]);
678
+ if (!feeTier || !wpcAddress)
679
+ return BigInt(0);
680
+ const QUOTER_ABI = [
681
+ {
682
+ type: 'function',
683
+ name: 'quoteExactOutputSingle',
684
+ inputs: [
732
685
  {
733
- tokenIn: prc20Token,
734
- tokenOut: wpcAddress,
735
- amount: desiredWpc,
736
- fee: feeTier,
737
- sqrtPriceLimitX96: BigInt(0),
686
+ type: 'tuple',
687
+ components: [
688
+ { name: 'tokenIn', type: 'address' },
689
+ { name: 'tokenOut', type: 'address' },
690
+ { name: 'amount', type: 'uint256' },
691
+ { name: 'fee', type: 'uint24' },
692
+ { name: 'sqrtPriceLimitX96', type: 'uint160' },
693
+ ],
738
694
  },
739
695
  ],
740
- });
741
- const amountIn = result[0];
742
- (0, context_1.printLog)(ctx, `estimateNativeForDesiredDeposit — quote: ${desiredWpc.toString()} WPC ← ${amountIn.toString()} pETH (fee tier: ${feeTier})`);
743
- return amountIn;
744
- }
745
- catch (err) {
746
- (0, context_1.printLog)(ctx, `estimateNativeForDesiredDeposit — failed: ${err instanceof Error ? err.message : String(err)}`);
747
- return BigInt(0);
748
- }
749
- });
696
+ outputs: [
697
+ { name: 'amountIn', type: 'uint256' },
698
+ { name: 'sqrtPriceX96After', type: 'uint160' },
699
+ { name: 'initializedTicksCrossed', type: 'uint32' },
700
+ { name: 'gasEstimate', type: 'uint256' },
701
+ ],
702
+ stateMutability: 'view',
703
+ },
704
+ ];
705
+ const result = await ctx.pushClient.readContract({
706
+ address: quoterAddress,
707
+ abi: QUOTER_ABI,
708
+ functionName: 'quoteExactOutputSingle',
709
+ args: [
710
+ {
711
+ tokenIn: prc20Token,
712
+ tokenOut: wpcAddress,
713
+ amount: desiredWpc,
714
+ fee: feeTier,
715
+ sqrtPriceLimitX96: BigInt(0),
716
+ },
717
+ ],
718
+ });
719
+ const amountIn = result[0];
720
+ (0, context_1.printLog)(ctx, `estimateNativeForDesiredDeposit — quote: ${desiredWpc.toString()} WPC ← ${amountIn.toString()} pETH (fee tier: ${feeTier})`);
721
+ return amountIn;
722
+ }
723
+ catch (err) {
724
+ (0, context_1.printLog)(ctx, `estimateNativeForDesiredDeposit — failed: ${err instanceof Error ? err.message : String(err)}`);
725
+ return BigInt(0);
726
+ }
750
727
  }
751
728
  //# sourceMappingURL=gas-calculator.js.map