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