@pushchain/core 5.1.4 → 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 +55 -7
- package/src/lib/orchestrator/internals/gas-calculator.d.ts +10 -0
- package/src/lib/orchestrator/internals/gas-calculator.js +95 -3
- package/src/lib/orchestrator/internals/gateway-client.js +6 -6
- package/src/lib/orchestrator/internals/route-handlers.js +27 -43
- package/src/lib/orchestrator/orchestrator.types.d.ts +2 -21
- 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) {
|
|
@@ -200,7 +200,34 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
|
|
|
200
200
|
const fundDifference = requiredFunds - funds;
|
|
201
201
|
const fixedPushAmount = utils_1.Utils.helpers.parseUnits('0.001', 18);
|
|
202
202
|
const lockAmount = funds < requiredFunds ? fundDifference : fixedPushAmount;
|
|
203
|
-
|
|
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
|
+
}
|
|
204
231
|
// Apply minimum deposit override (e.g., Route 2 needs enough UPC for outbound swap)
|
|
205
232
|
const effectiveLockAmountInUSD = execute._minimumDepositUsd && execute._minimumDepositUsd > lockAmountInUSD
|
|
206
233
|
? execute._minimumDepositUsd
|
|
@@ -212,12 +239,12 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
|
|
|
212
239
|
const { vm: originVm } = chain_1.CHAIN_INFO[chain];
|
|
213
240
|
if (originVm === enums_1.VM.EVM) {
|
|
214
241
|
try {
|
|
215
|
-
// Replicate lockFee's USD → native conversion (with its $1–$
|
|
242
|
+
// Replicate lockFee's USD → native conversion (with its $1–$1000 clamp)
|
|
216
243
|
const oneUsd = utils_1.Utils.helpers.parseUnits('1', 8);
|
|
217
|
-
const
|
|
244
|
+
const maxUsd = utils_1.Utils.helpers.parseUnits('1000', 8);
|
|
218
245
|
let depositUsd = effectiveLockAmountInUSD < oneUsd ? oneUsd : effectiveLockAmountInUSD;
|
|
219
|
-
if (depositUsd >
|
|
220
|
-
depositUsd =
|
|
246
|
+
if (depositUsd > maxUsd)
|
|
247
|
+
depositUsd = maxUsd;
|
|
221
248
|
const ethPrice = yield new price_fetch_1.PriceFetch(ctx.rpcUrls).getPrice(chain);
|
|
222
249
|
if (ethPrice > BigInt(0)) {
|
|
223
250
|
const nativeAmountETH = (depositUsd * BigInt(1e18) + (ethPrice - BigInt(1))) / ethPrice + BigInt(1);
|
|
@@ -233,11 +260,32 @@ function executeStandardPayload(ctx, execute, eventBuffer, getResponseCallbacks)
|
|
|
233
260
|
`total: ${totalAvailable.toString()}, required: ${requiredFunds.toString()}`);
|
|
234
261
|
if (totalAvailable < requiredFunds) {
|
|
235
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
|
+
}
|
|
236
283
|
throw new Error(`Insufficient deposit: the fee-lock will deposit ~${(Number(safeUPC) / 1e18).toFixed(4)} $PC ` +
|
|
237
284
|
`but the transaction requires ~${(Number(requiredFunds) / 1e18).toFixed(4)} $PC ` +
|
|
238
285
|
`(shortfall: ~${(Number(shortfall) / 1e18).toFixed(4)} $PC). ` +
|
|
239
|
-
`The fee-lock deposit is capped at $
|
|
240
|
-
|
|
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.`);
|
|
241
289
|
}
|
|
242
290
|
}
|
|
243
291
|
}
|
|
@@ -45,3 +45,13 @@ export declare function calculateGasAmountFromAmountOutMinETH(ctx: OrchestratorC
|
|
|
45
45
|
* Returns 0 on any failure (caller should fall back to other logic).
|
|
46
46
|
*/
|
|
47
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>;
|
|
@@ -11,6 +11,7 @@ exports.queryRescueGasFee = queryRescueGasFee;
|
|
|
11
11
|
exports.calculateNativeAmountForDeposit = calculateNativeAmountForDeposit;
|
|
12
12
|
exports.calculateGasAmountFromAmountOutMinETH = calculateGasAmountFromAmountOutMinETH;
|
|
13
13
|
exports.estimateDepositFromLockedNative = estimateDepositFromLockedNative;
|
|
14
|
+
exports.estimateNativeForDesiredDeposit = estimateNativeForDesiredDeposit;
|
|
14
15
|
const tslib_1 = require("tslib");
|
|
15
16
|
const web3_js_1 = require("@solana/web3.js");
|
|
16
17
|
const viem_1 = require("viem");
|
|
@@ -336,13 +337,13 @@ function calculateNativeAmountForDeposit(ctx, chain, requiredFunds, ueaBalance)
|
|
|
336
337
|
var _a, _b;
|
|
337
338
|
(0, context_1.fireProgressHook)(ctx, progress_hook_types_1.PROGRESS_HOOK.SEND_TX_02_01);
|
|
338
339
|
const oneUsd = utils_1.Utils.helpers.parseUnits('1', 8);
|
|
339
|
-
const
|
|
340
|
+
const maxUsd = utils_1.Utils.helpers.parseUnits('1000', 8);
|
|
340
341
|
const deficit = requiredFunds > ueaBalance ? requiredFunds - ueaBalance : BigInt(0);
|
|
341
342
|
let depositUsd = deficit > BigInt(0) ? ctx.pushClient.pushToUSDC(deficit) : oneUsd;
|
|
342
343
|
if (depositUsd < oneUsd)
|
|
343
344
|
depositUsd = oneUsd;
|
|
344
|
-
if (depositUsd >
|
|
345
|
-
throw new Error('Deposit value exceeds max $
|
|
345
|
+
if (depositUsd > maxUsd)
|
|
346
|
+
throw new Error('Deposit value exceeds max $1000 worth of native token');
|
|
346
347
|
if (chain_1.CHAIN_INFO[chain].vm === enums_1.VM.SVM) {
|
|
347
348
|
const svmClient = new svm_client_1.SvmClient({
|
|
348
349
|
rpcUrls: ctx.rpcUrls[enums_1.CHAIN.SOLANA_DEVNET] ||
|
|
@@ -515,4 +516,95 @@ function estimateDepositFromLockedNative(ctx, nativeAmountForLocker, prc20Token)
|
|
|
515
516
|
}
|
|
516
517
|
});
|
|
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
|
+
}
|
|
518
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;
|
|
@@ -35,6 +35,7 @@ const utils_1 = require("../../utils");
|
|
|
35
35
|
const price_fetch_1 = require("../../price-fetch/price-fetch");
|
|
36
36
|
const route_detector_1 = require("../route-detector");
|
|
37
37
|
const cea_utils_1 = require("../cea-utils");
|
|
38
|
+
const build_payload_1 = require("../svm-idl/build-payload");
|
|
38
39
|
const payload_builders_1 = require("../payload-builders");
|
|
39
40
|
const selectors_1 = require("../../constants/selectors");
|
|
40
41
|
const erc20_evm_1 = require("../../constants/abi/erc20.evm");
|
|
@@ -393,22 +394,15 @@ function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
|
393
394
|
const targetChain = target.chain;
|
|
394
395
|
const targetAddress = target.address; // 0x-prefixed, 32 bytes
|
|
395
396
|
const ueaAddress = (0, uea_manager_1.computeUEAOffchain)(ctx);
|
|
396
|
-
const hasSvmExecute =
|
|
397
|
+
const { svmPayload, targetBytes, hasExecute: hasSvmExecute, } = (0, build_payload_1.buildSvmPayloadFromParams)({
|
|
398
|
+
data: params.data,
|
|
399
|
+
to: target,
|
|
400
|
+
senderUea: ueaAddress,
|
|
401
|
+
});
|
|
397
402
|
(0, context_1.printLog)(ctx, `executeUoaToCeaSvm — target: ${targetAddress}, chain: ${targetChain}, ` +
|
|
398
403
|
`hasSvmExecute: ${hasSvmExecute}, value: ${(_b = (_a = params.value) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '0'}`);
|
|
399
|
-
// --- Build SVM payload ---
|
|
400
|
-
let svmPayload = '0x'; // empty for withdraw (SOL/SPL)
|
|
401
404
|
if (hasSvmExecute) {
|
|
402
|
-
|
|
403
|
-
const exec = params.svmExecute;
|
|
404
|
-
svmPayload = (0, payload_builders_1.encodeSvmExecutePayload)({
|
|
405
|
-
targetProgram: exec.targetProgram,
|
|
406
|
-
accounts: exec.accounts,
|
|
407
|
-
ixData: exec.ixData,
|
|
408
|
-
instructionId: 2,
|
|
409
|
-
});
|
|
410
|
-
(0, context_1.printLog)(ctx, `executeUoaToCeaSvm — encoded execute payload: ${(svmPayload.length - 2) / 2} bytes, ` +
|
|
411
|
-
`${exec.accounts.length} accounts`);
|
|
405
|
+
(0, context_1.printLog)(ctx, `executeUoaToCeaSvm — encoded execute payload: ${(svmPayload.length - 2) / 2} bytes`);
|
|
412
406
|
}
|
|
413
407
|
// --- Determine PRC-20 token and burn amount ---
|
|
414
408
|
let prc20Token = selectors_1.ZERO_ADDRESS;
|
|
@@ -439,13 +433,8 @@ function executeUoaToCeaSvm(ctx, params, target, executeFn) {
|
|
|
439
433
|
burnAmount = BigInt(0);
|
|
440
434
|
(0, context_1.printLog)(ctx, `executeUoaToCeaSvm — EXECUTE-only: using PRC-20 ${prc20Token} with zero burn amount`);
|
|
441
435
|
}
|
|
442
|
-
// --- Determine target bytes ---
|
|
443
|
-
// For withdraw: target is the Solana recipient pubkey
|
|
444
|
-
// For execute: target is the target Solana program
|
|
445
|
-
const targetBytes = hasSvmExecute
|
|
446
|
-
? params.svmExecute.targetProgram
|
|
447
|
-
: targetAddress;
|
|
448
436
|
// --- Build outbound request ---
|
|
437
|
+
// targetBytes: for execute = program id (resolver output); for withdraw = to.address
|
|
449
438
|
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetBytes, prc20Token, burnAmount, (_d = params.gasLimit) !== null && _d !== void 0 ? _d : BigInt(0), svmPayload, ueaAddress // revert recipient is the UEA
|
|
450
439
|
);
|
|
451
440
|
(0, context_1.printLog)(ctx, `executeUoaToCeaSvm — outbound request: ${JSON.stringify({
|
|
@@ -972,7 +961,7 @@ function executeCeaToCea(ctx, params, executeFn) {
|
|
|
972
961
|
*/
|
|
973
962
|
function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
974
963
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
975
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l
|
|
964
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
976
965
|
const ueaAddress = (0, uea_manager_1.computeUEAOffchain)(ctx);
|
|
977
966
|
switch (route) {
|
|
978
967
|
case route_detector_1.TransactionRoute.UOA_TO_PUSH: {
|
|
@@ -995,20 +984,15 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
995
984
|
const target = params.to;
|
|
996
985
|
// Branch: SVM vs EVM
|
|
997
986
|
if ((0, payload_builders_1.isSvmChain)(target.chain)) {
|
|
998
|
-
// SVM: build SVM payload (binary or empty for withdraw)
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
ixData: params.svmExecute.ixData,
|
|
1005
|
-
instructionId: 2,
|
|
1006
|
-
});
|
|
1007
|
-
}
|
|
1008
|
-
const targetBytes = (_b = (_a = params.svmExecute) === null || _a === void 0 ? void 0 : _a.targetProgram) !== null && _b !== void 0 ? _b : target.address;
|
|
987
|
+
// SVM: build SVM payload (binary or empty for withdraw) via IDL resolver
|
|
988
|
+
const { svmPayload: payload, targetBytes, hasExecute, } = (0, build_payload_1.buildSvmPayloadFromParams)({
|
|
989
|
+
data: params.data,
|
|
990
|
+
to: target,
|
|
991
|
+
senderUea: ueaAddress,
|
|
992
|
+
});
|
|
1009
993
|
let prc20Token = selectors_1.ZERO_ADDRESS;
|
|
1010
994
|
let burnAmount = BigInt(0);
|
|
1011
|
-
if ((
|
|
995
|
+
if ((_a = params.funds) === null || _a === void 0 ? void 0 : _a.amount) {
|
|
1012
996
|
const token = params.funds.token;
|
|
1013
997
|
if (token) {
|
|
1014
998
|
prc20Token = push_chain_1.PushChain.utils.tokens.getPRC20Address(token);
|
|
@@ -1019,15 +1003,15 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1019
1003
|
prc20Token = (0, helpers_1.getNativePRC20ForChain)(target.chain, ctx.pushNetwork);
|
|
1020
1004
|
burnAmount = params.value;
|
|
1021
1005
|
}
|
|
1022
|
-
else if (
|
|
1006
|
+
else if (hasExecute) {
|
|
1023
1007
|
prc20Token = (0, helpers_1.getNativePRC20ForChain)(target.chain, ctx.pushNetwork);
|
|
1024
1008
|
burnAmount = BigInt(1);
|
|
1025
1009
|
}
|
|
1026
|
-
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetBytes, prc20Token, burnAmount, (
|
|
1010
|
+
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetBytes, prc20Token, burnAmount, (_b = params.gasLimit) !== null && _b !== void 0 ? _b : BigInt(0), payload, ueaAddress);
|
|
1027
1011
|
return { payload, gatewayRequest: outboundReq };
|
|
1028
1012
|
}
|
|
1029
1013
|
// EVM path: Resolve CEA address first (needed for self-transfer check)
|
|
1030
|
-
const { cea: ceaAddress } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, target.chain, (
|
|
1014
|
+
const { cea: ceaAddress } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, target.chain, (_c = ctx.rpcUrls[target.chain]) === null || _c === void 0 ? void 0 : _c[0]);
|
|
1031
1015
|
// Build CEA outbound payload
|
|
1032
1016
|
const multicalls = [];
|
|
1033
1017
|
if (params.data) {
|
|
@@ -1060,7 +1044,7 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1060
1044
|
const payload = (0, payload_builders_1.buildCeaMulticallPayload)(multicalls);
|
|
1061
1045
|
let prc20Token = selectors_1.ZERO_ADDRESS;
|
|
1062
1046
|
let burnAmount = BigInt(0);
|
|
1063
|
-
if ((
|
|
1047
|
+
if ((_d = params.funds) === null || _d === void 0 ? void 0 : _d.amount) {
|
|
1064
1048
|
const token = params.funds.token;
|
|
1065
1049
|
if (token) {
|
|
1066
1050
|
prc20Token = push_chain_1.PushChain.utils.tokens.getPRC20Address(token);
|
|
@@ -1068,13 +1052,13 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1068
1052
|
}
|
|
1069
1053
|
}
|
|
1070
1054
|
const targetBytes = ceaAddress;
|
|
1071
|
-
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetBytes, prc20Token, burnAmount, (
|
|
1055
|
+
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(targetBytes, prc20Token, burnAmount, (_e = params.gasLimit) !== null && _e !== void 0 ? _e : BigInt(0), payload, ueaAddress);
|
|
1072
1056
|
return { payload, gatewayRequest: outboundReq };
|
|
1073
1057
|
}
|
|
1074
1058
|
case route_detector_1.TransactionRoute.CEA_TO_PUSH: {
|
|
1075
1059
|
// Route 3: CEA -> Push Chain
|
|
1076
1060
|
// Build CEA multicall (approve + sendUniversalTxFromCEA) and wrap in outbound
|
|
1077
|
-
if (!((
|
|
1061
|
+
if (!((_f = params.from) === null || _f === void 0 ? void 0 : _f.chain)) {
|
|
1078
1062
|
throw new Error('Route 3 (CEA -> Push) requires from.chain');
|
|
1079
1063
|
}
|
|
1080
1064
|
const sourceChain = params.from.chain;
|
|
@@ -1089,7 +1073,7 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1089
1073
|
const gatewayProgramHex = ('0x' + Buffer.from(programPk.toBytes()).toString('hex'));
|
|
1090
1074
|
let drainAmount = BigInt(0);
|
|
1091
1075
|
let tokenMintHex;
|
|
1092
|
-
if (((
|
|
1076
|
+
if (((_g = params.funds) === null || _g === void 0 ? void 0 : _g.amount) && params.funds.amount > BigInt(0)) {
|
|
1093
1077
|
drainAmount = params.funds.amount;
|
|
1094
1078
|
const token = params.funds.token;
|
|
1095
1079
|
if (token && token.address) {
|
|
@@ -1114,10 +1098,10 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1114
1098
|
});
|
|
1115
1099
|
// burnAmount = 1 (minimum for precompile; drain amount lives inside the ixData)
|
|
1116
1100
|
const burnAmount = BigInt(1);
|
|
1117
|
-
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(gatewayProgramHex, prc20Token, burnAmount, (
|
|
1101
|
+
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(gatewayProgramHex, prc20Token, burnAmount, (_h = params.gasLimit) !== null && _h !== void 0 ? _h : BigInt(0), svmPayload, ueaAddress);
|
|
1118
1102
|
return { payload: svmPayload, gatewayRequest: outboundReq };
|
|
1119
1103
|
}
|
|
1120
|
-
const { cea: ceaAddress } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, sourceChain, (
|
|
1104
|
+
const { cea: ceaAddress } = yield (0, cea_utils_1.getCEAAddress)(ueaAddress, sourceChain, (_j = ctx.rpcUrls[sourceChain]) === null || _j === void 0 ? void 0 : _j[0]);
|
|
1121
1105
|
// CEA auto-deploys on-chain: Vault.finalizeUniversalTx calls CEAFactory.deployCEA()
|
|
1122
1106
|
// if CEA doesn't exist yet. No SDK-side blocking needed.
|
|
1123
1107
|
const gatewayAddr = chain_1.UNIVERSAL_GATEWAY_ADDRESSES[sourceChain];
|
|
@@ -1128,7 +1112,7 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1128
1112
|
const ceaMulticalls = [];
|
|
1129
1113
|
let tokenAddress = selectors_1.ZERO_ADDRESS;
|
|
1130
1114
|
let amount = BigInt(0);
|
|
1131
|
-
if ((
|
|
1115
|
+
if ((_k = params.funds) === null || _k === void 0 ? void 0 : _k.amount) {
|
|
1132
1116
|
const token = params.funds.token;
|
|
1133
1117
|
if (token) {
|
|
1134
1118
|
if (token.mechanism === 'native') {
|
|
@@ -1192,7 +1176,7 @@ function buildPayloadForRoute(ctx, params, route, nonce) {
|
|
|
1192
1176
|
// Route 3: CEA uses its own pre-existing balance — no PRC-20 burn needed.
|
|
1193
1177
|
// burnAmount = 0 makes this a payload-only outbound relay.
|
|
1194
1178
|
const burnAmount = BigInt(0);
|
|
1195
|
-
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(ceaAddress, prc20Token, burnAmount, (
|
|
1179
|
+
const outboundReq = (0, payload_builders_1.buildOutboundRequest)(ceaAddress, prc20Token, burnAmount, (_l = params.gasLimit) !== null && _l !== void 0 ? _l : BigInt(0), ceaPayload, ueaAddress);
|
|
1196
1180
|
return { payload: ceaPayload, gatewayRequest: outboundReq };
|
|
1197
1181
|
}
|
|
1198
1182
|
default:
|
|
@@ -110,7 +110,7 @@ export type ExecuteParams = {
|
|
|
110
110
|
* Internal: Minimum fee-locking deposit in USD (8 decimals).
|
|
111
111
|
* Overrides the default $1 floor when the caller needs a larger deposit
|
|
112
112
|
* (e.g., Route 2 needs enough UPC for the outbound swap).
|
|
113
|
-
* Still capped at $
|
|
113
|
+
* Still capped at $1000 by lockFee.
|
|
114
114
|
* @internal
|
|
115
115
|
*/
|
|
116
116
|
_minimumDepositUsd?: bigint;
|
|
@@ -291,16 +291,9 @@ export type UniversalExecuteParams = Omit<ExecuteParams, 'to'> & {
|
|
|
291
291
|
* - ChainTarget: External chain target (Routes 2, 3, 4)
|
|
292
292
|
*/
|
|
293
293
|
to: UniversalTo;
|
|
294
|
-
/**
|
|
295
|
-
* SVM-specific: CPI execution parameters for Solana targets (Route 2).
|
|
296
|
-
* When present, the outbound transaction will execute a Cross-Program Invocation
|
|
297
|
-
* on the specified Solana program with the given accounts and instruction data.
|
|
298
|
-
* Only applicable when `to.chain` is a Solana chain.
|
|
299
|
-
*/
|
|
300
|
-
svmExecute?: SvmExecuteParams;
|
|
301
294
|
/**
|
|
302
295
|
* When true, sends MIGRATION_SELECTOR as raw CEA payload (no multicall wrapping).
|
|
303
|
-
* Used for CEA contract upgrades. Incompatible with value/funds/data
|
|
296
|
+
* Used for CEA contract upgrades. Incompatible with value/funds/data.
|
|
304
297
|
* Only applicable for Route 2 (UOA_TO_CEA) on EVM chains.
|
|
305
298
|
*/
|
|
306
299
|
migration?: boolean;
|
|
@@ -329,18 +322,6 @@ export interface SvmExecutePayloadFields {
|
|
|
329
322
|
/** Instruction ID: 2 = execute (default) */
|
|
330
323
|
instructionId?: number;
|
|
331
324
|
}
|
|
332
|
-
/**
|
|
333
|
-
* User-facing parameters for CPI execution on a Solana program via Route 2.
|
|
334
|
-
* Passed as `svmExecute` in UniversalExecuteParams when targeting SVM chains.
|
|
335
|
-
*/
|
|
336
|
-
export interface SvmExecuteParams {
|
|
337
|
-
/** Target Solana program to CPI into (32 bytes, 0x-prefixed hex) */
|
|
338
|
-
targetProgram: `0x${string}`;
|
|
339
|
-
/** Accounts required for the CPI call */
|
|
340
|
-
accounts: SvmGatewayAccountMeta[];
|
|
341
|
-
/** Raw instruction data for the target program */
|
|
342
|
-
ixData: Uint8Array;
|
|
343
|
-
}
|
|
344
325
|
/**
|
|
345
326
|
* Request structure for sendUniversalTxOutbound on Push Chain
|
|
346
327
|
* Used for Routes 2, 3, 4 (outbound from Push)
|
|
@@ -249,9 +249,6 @@ function validateRouteParams(params, context) {
|
|
|
249
249
|
if (params.data) {
|
|
250
250
|
throw new RouteValidationError('migration is incompatible with data');
|
|
251
251
|
}
|
|
252
|
-
if (params.svmExecute) {
|
|
253
|
-
throw new RouteValidationError('migration is incompatible with svmExecute');
|
|
254
|
-
}
|
|
255
252
|
if (isChainTarget(params.to) && (0, payload_builders_1.isSvmChain)(params.to.chain)) {
|
|
256
253
|
throw new RouteValidationError('migration is not supported on SVM chains');
|
|
257
254
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ChainTarget } from '../orchestrator.types';
|
|
2
|
+
export interface SvmPayloadBundle {
|
|
3
|
+
svmPayload: `0x${string}`;
|
|
4
|
+
targetBytes: `0x${string}`;
|
|
5
|
+
hasExecute: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function buildSvmPayloadFromParams(params: {
|
|
8
|
+
data?: `0x${string}` | unknown;
|
|
9
|
+
to: ChainTarget;
|
|
10
|
+
senderUea: `0x${string}`;
|
|
11
|
+
}): SvmPayloadBundle;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildSvmPayloadFromParams = buildSvmPayloadFromParams;
|
|
4
|
+
const viem_1 = require("viem");
|
|
5
|
+
const payload_builders_1 = require("../payload-builders");
|
|
6
|
+
const resolve_1 = require("./resolve");
|
|
7
|
+
function buildSvmPayloadFromParams(params) {
|
|
8
|
+
const hasExecute = typeof params.data === 'string' &&
|
|
9
|
+
params.data.startsWith('0x') &&
|
|
10
|
+
params.data.length > 2;
|
|
11
|
+
if (!hasExecute) {
|
|
12
|
+
return {
|
|
13
|
+
svmPayload: '0x',
|
|
14
|
+
targetBytes: params.to.address,
|
|
15
|
+
hasExecute: false,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const resolved = (0, resolve_1.resolveSvmCall)({
|
|
19
|
+
programAddress: params.to.address,
|
|
20
|
+
data: (0, viem_1.hexToBytes)(params.data),
|
|
21
|
+
senderUea: params.senderUea,
|
|
22
|
+
targetChain: params.to.chain,
|
|
23
|
+
});
|
|
24
|
+
const svmPayload = (0, payload_builders_1.encodeSvmExecutePayload)({
|
|
25
|
+
targetProgram: resolved.targetProgram,
|
|
26
|
+
accounts: resolved.accounts,
|
|
27
|
+
ixData: resolved.ixData,
|
|
28
|
+
instructionId: 2,
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
svmPayload,
|
|
32
|
+
targetBytes: resolved.targetProgram,
|
|
33
|
+
hasExecute: true,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=build-payload.js.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.encodeAnchorIxData = encodeAnchorIxData;
|
|
4
|
+
exports.isAnchorIdl = isAnchorIdl;
|
|
5
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
6
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
7
|
+
const buffer_1 = require("buffer");
|
|
8
|
+
function encodeAnchorIxData(idl, functionName, positionalArgs = []) {
|
|
9
|
+
var _a, _b;
|
|
10
|
+
const ix = findInstruction(idl, functionName);
|
|
11
|
+
if (!ix) {
|
|
12
|
+
throw new Error(`Instruction '${functionName}' not found in IDL '${(_b = (_a = idl.metadata) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : 'unknown'}'`);
|
|
13
|
+
}
|
|
14
|
+
if (positionalArgs.length !== ix.args.length) {
|
|
15
|
+
throw new Error(`Arg count mismatch for '${ix.name}': IDL expects ${ix.args.length}, got ${positionalArgs.length}`);
|
|
16
|
+
}
|
|
17
|
+
const named = {};
|
|
18
|
+
for (let i = 0; i < ix.args.length; i++) {
|
|
19
|
+
named[ix.args[i].name] = normalizeArg(positionalArgs[i], ix.args[i]);
|
|
20
|
+
}
|
|
21
|
+
const coder = new anchor_1.BorshInstructionCoder(idl);
|
|
22
|
+
return new Uint8Array(coder.encode(ix.name, named));
|
|
23
|
+
}
|
|
24
|
+
function findInstruction(idl, name) {
|
|
25
|
+
const snake = name.replace(/([A-Z])/g, (_, c) => '_' + c.toLowerCase());
|
|
26
|
+
const camel = name.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
27
|
+
return idl.instructions.find((i) => i.name === name || i.name === snake || i.name === camel);
|
|
28
|
+
}
|
|
29
|
+
function normalizeArg(value, field) {
|
|
30
|
+
if (typeof value === 'bigint') {
|
|
31
|
+
return new anchor_1.BN(value.toString());
|
|
32
|
+
}
|
|
33
|
+
if (field.type === 'pubkey' &&
|
|
34
|
+
typeof value === 'string' &&
|
|
35
|
+
value.startsWith('0x') &&
|
|
36
|
+
value.length === 66) {
|
|
37
|
+
return new web3_js_1.PublicKey(buffer_1.Buffer.from(value.slice(2), 'hex'));
|
|
38
|
+
}
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
function isAnchorIdl(value) {
|
|
42
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
43
|
+
return false;
|
|
44
|
+
const maybe = value;
|
|
45
|
+
return Array.isArray(maybe['instructions']) && typeof maybe['address'] === 'string';
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=ix-encoder.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Idl } from '@coral-xyz/anchor';
|
|
2
|
+
type AddressKey = `0x${string}`;
|
|
3
|
+
export declare function registerIdl(programAddress: string, idl: unknown): void;
|
|
4
|
+
export declare function getIdl(programAddress: string): Idl | undefined;
|
|
5
|
+
export declare function getRegisteredIdls(): Array<{
|
|
6
|
+
address: AddressKey;
|
|
7
|
+
idl: Idl;
|
|
8
|
+
}>;
|
|
9
|
+
export declare function clearRegistry(): void;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerIdl = registerIdl;
|
|
4
|
+
exports.getIdl = getIdl;
|
|
5
|
+
exports.getRegisteredIdls = getRegisteredIdls;
|
|
6
|
+
exports.clearRegistry = clearRegistry;
|
|
7
|
+
const ix_encoder_1 = require("./ix-encoder");
|
|
8
|
+
const store = new Map();
|
|
9
|
+
function normalizeKey(address) {
|
|
10
|
+
if (typeof address !== 'string' || !address.startsWith('0x')) {
|
|
11
|
+
throw new Error(`registerIdl: programAddress must be 0x-prefixed 32-byte hex, got '${address}'`);
|
|
12
|
+
}
|
|
13
|
+
const body = address.slice(2);
|
|
14
|
+
if (body.length !== 64 || !/^[0-9a-fA-F]+$/.test(body)) {
|
|
15
|
+
throw new Error(`registerIdl: programAddress must be 32 bytes (66 chars incl. 0x), got length ${address.length}`);
|
|
16
|
+
}
|
|
17
|
+
return ('0x' + body.toLowerCase());
|
|
18
|
+
}
|
|
19
|
+
function registerIdl(programAddress, idl) {
|
|
20
|
+
const key = normalizeKey(programAddress);
|
|
21
|
+
if (!(0, ix_encoder_1.isAnchorIdl)(idl)) {
|
|
22
|
+
throw new Error(`registerIdl: idl for ${programAddress} is not a recognized Anchor IDL (missing 'instructions' or 'address')`);
|
|
23
|
+
}
|
|
24
|
+
store.set(key, idl);
|
|
25
|
+
}
|
|
26
|
+
function getIdl(programAddress) {
|
|
27
|
+
const key = normalizeKey(programAddress);
|
|
28
|
+
return store.get(key);
|
|
29
|
+
}
|
|
30
|
+
function getRegisteredIdls() {
|
|
31
|
+
return Array.from(store.entries()).map(([address, idl]) => ({ address, idl }));
|
|
32
|
+
}
|
|
33
|
+
function clearRegistry() {
|
|
34
|
+
store.clear();
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { CHAIN } from '../../constants/enums';
|
|
2
|
+
import type { SvmGatewayAccountMeta } from '../orchestrator.types';
|
|
3
|
+
export interface ResolveInput {
|
|
4
|
+
programAddress: `0x${string}`;
|
|
5
|
+
data: Uint8Array;
|
|
6
|
+
senderUea: `0x${string}`;
|
|
7
|
+
targetChain: CHAIN;
|
|
8
|
+
}
|
|
9
|
+
export interface ResolvedSvmCall {
|
|
10
|
+
targetProgram: `0x${string}`;
|
|
11
|
+
accounts: SvmGatewayAccountMeta[];
|
|
12
|
+
ixData: Uint8Array;
|
|
13
|
+
}
|
|
14
|
+
export declare function resolveSvmCall(input: ResolveInput): ResolvedSvmCall;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveSvmCall = resolveSvmCall;
|
|
4
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
5
|
+
const buffer_1 = require("buffer");
|
|
6
|
+
const account_1 = require("../../universal/account/account");
|
|
7
|
+
const registry_1 = require("./registry");
|
|
8
|
+
const CEA_AUTHORITY_NAMES = new Set([
|
|
9
|
+
'cea_authority',
|
|
10
|
+
'ceaAuthority',
|
|
11
|
+
'cea',
|
|
12
|
+
'cea_signer',
|
|
13
|
+
'ceaSigner',
|
|
14
|
+
]);
|
|
15
|
+
function resolveSvmCall(input) {
|
|
16
|
+
var _a, _b;
|
|
17
|
+
const idl = (0, registry_1.getIdl)(input.programAddress);
|
|
18
|
+
if (!idl) {
|
|
19
|
+
throw new Error(`resolveSvmCall: no IDL registered for ${input.programAddress}. ` +
|
|
20
|
+
`Call PushChain.utils.svm.registerIdl(${input.programAddress}, idl) first.`);
|
|
21
|
+
}
|
|
22
|
+
if (input.data.length < 8) {
|
|
23
|
+
throw new Error('resolveSvmCall: data must be at least 8 bytes (Anchor discriminator)');
|
|
24
|
+
}
|
|
25
|
+
const disc = input.data.slice(0, 8);
|
|
26
|
+
const ix = idl.instructions.find((i) => buffer_1.Buffer.from(i.discriminator).equals(buffer_1.Buffer.from(disc)));
|
|
27
|
+
if (!ix) {
|
|
28
|
+
throw new Error(`resolveSvmCall: no instruction in IDL '${(_b = (_a = idl.metadata) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : idl.address}' matches discriminator [${Array.from(disc).join(',')}]`);
|
|
29
|
+
}
|
|
30
|
+
const programPk = new web3_js_1.PublicKey(buffer_1.Buffer.from(input.programAddress.slice(2), 'hex'));
|
|
31
|
+
const { address: ceaPdaHex } = (0, account_1.deriveSvmCeaPda)(input.senderUea, input.targetChain, true);
|
|
32
|
+
const accounts = [];
|
|
33
|
+
for (const item of ix.accounts) {
|
|
34
|
+
if ('accounts' in item) {
|
|
35
|
+
throw new Error(`resolveSvmCall: nested account group '${item.name}' in '${ix.name}' not supported`);
|
|
36
|
+
}
|
|
37
|
+
const flat = item;
|
|
38
|
+
const pubkey = resolveAccountPubkey(flat, programPk, ceaPdaHex, ix.name);
|
|
39
|
+
accounts.push({ pubkey, isWritable: Boolean(flat.writable) });
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
targetProgram: input.programAddress,
|
|
43
|
+
accounts,
|
|
44
|
+
ixData: input.data,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function resolveAccountPubkey(spec, programPk, ceaPdaHex, ixName) {
|
|
48
|
+
if (spec.address) {
|
|
49
|
+
return pkToHex(new web3_js_1.PublicKey(spec.address));
|
|
50
|
+
}
|
|
51
|
+
if (spec.pda) {
|
|
52
|
+
const seeds = resolveConstSeeds(spec.pda.seeds, spec.name, ixName);
|
|
53
|
+
const programForPda = spec.pda.program
|
|
54
|
+
? new web3_js_1.PublicKey(resolveConstSeedValue(spec.pda.program, spec.name, ixName))
|
|
55
|
+
: programPk;
|
|
56
|
+
const [pda] = web3_js_1.PublicKey.findProgramAddressSync(seeds, programForPda);
|
|
57
|
+
return pkToHex(pda);
|
|
58
|
+
}
|
|
59
|
+
if (CEA_AUTHORITY_NAMES.has(spec.name)) {
|
|
60
|
+
return ceaPdaHex;
|
|
61
|
+
}
|
|
62
|
+
throw new Error(`resolveSvmCall: cannot resolve account '${spec.name}' in '${ixName}'. ` +
|
|
63
|
+
`Add 'address' or 'pda.seeds' to the IDL, or rename to a CEA convention (cea_authority).`);
|
|
64
|
+
}
|
|
65
|
+
function resolveConstSeeds(seeds, accountName, ixName) {
|
|
66
|
+
return seeds.map((seed, idx) => {
|
|
67
|
+
if (seed.kind !== 'const') {
|
|
68
|
+
throw new Error(`resolveSvmCall: non-const PDA seed (kind='${seed.kind}') on account '${accountName}' in '${ixName}' not supported yet`);
|
|
69
|
+
}
|
|
70
|
+
if (!Array.isArray(seed.value)) {
|
|
71
|
+
throw new Error(`resolveSvmCall: const seed at index ${idx} on '${accountName}' is malformed`);
|
|
72
|
+
}
|
|
73
|
+
return buffer_1.Buffer.from(seed.value);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function resolveConstSeedValue(seed, accountName, ixName) {
|
|
77
|
+
if (seed.kind !== 'const' || !Array.isArray(seed.value)) {
|
|
78
|
+
throw new Error(`resolveSvmCall: only const program-seed supported on '${accountName}' in '${ixName}'`);
|
|
79
|
+
}
|
|
80
|
+
return buffer_1.Buffer.from(seed.value);
|
|
81
|
+
}
|
|
82
|
+
function pkToHex(pk) {
|
|
83
|
+
return ('0x' + buffer_1.Buffer.from(pk.toBytes()).toString('hex'));
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -396,15 +396,25 @@ class PushChain {
|
|
|
396
396
|
*/
|
|
397
397
|
validatedUniversalSigner, (_c = options === null || options === void 0 ? void 0 : options.network) !== null && _c !== void 0 ? _c : enums_1.PUSH_NETWORK.TESTNET_DONUT, (_d = options === null || options === void 0 ? void 0 : options.rpcUrls) !== null && _d !== void 0 ? _d : {}, (_e = options === null || options === void 0 ? void 0 : options.printTraces) !== null && _e !== void 0 ? _e : false, options === null || options === void 0 ? void 0 : options.progressHook);
|
|
398
398
|
const instance = new _a(orchestrator, validatedUniversalSigner, blockExplorers, isReadOnly);
|
|
399
|
-
// Background fetch account status (non-blocking, 30s timeout)
|
|
400
|
-
//
|
|
399
|
+
// Background fetch account status (non-blocking, 30s timeout).
|
|
400
|
+
// The timer must be cleared once the race settles — otherwise the
|
|
401
|
+
// unref'd setTimeout keeps the Node event loop alive for the full
|
|
402
|
+
// 30s after the caller's work is done, making scripts appear "stuck".
|
|
401
403
|
const ACCOUNT_STATUS_TIMEOUT = 30000;
|
|
404
|
+
let accountStatusTimer;
|
|
402
405
|
instance.accountStatusReady = Promise.race([
|
|
403
406
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
404
407
|
instance.getAccountStatus().then(() => { }),
|
|
405
|
-
new Promise((_, reject) =>
|
|
406
|
-
|
|
408
|
+
new Promise((_, reject) => {
|
|
409
|
+
accountStatusTimer = setTimeout(() => reject(new Error('Account status fetch timed out')), ACCOUNT_STATUS_TIMEOUT);
|
|
410
|
+
}),
|
|
411
|
+
])
|
|
412
|
+
.catch(() => {
|
|
407
413
|
// Silently ignore — lazy check in execute() will retry if needed
|
|
414
|
+
})
|
|
415
|
+
.finally(() => {
|
|
416
|
+
if (accountStatusTimer)
|
|
417
|
+
clearTimeout(accountStatusTimer);
|
|
408
418
|
});
|
|
409
419
|
// Let execute() await the background fetch instead of re-fetching
|
|
410
420
|
orchestrator.accountStatusReadyPromise = instance.accountStatusReady;
|
|
@@ -68,6 +68,19 @@ export declare function convertExecutorToOrigin(executorAddress: string, options
|
|
|
68
68
|
/** @internal Skip deprecation warning for SDK-internal calls */
|
|
69
69
|
_internal?: boolean;
|
|
70
70
|
}): Promise<OriginAccountInfo>;
|
|
71
|
+
/**
|
|
72
|
+
* Derive the SVM CEA (PDA) for a UEA address on a Solana-based chain.
|
|
73
|
+
*
|
|
74
|
+
* Solana doesn't use a CEAFactory contract — instead, the CEA is a
|
|
75
|
+
* Program Derived Address (PDA) with seeds: ["push_identity", ueaBytes]
|
|
76
|
+
* and the SVM gateway program as the program ID.
|
|
77
|
+
*
|
|
78
|
+
* @param ueaAddress - The UEA (or Push EOA) hex address (20 bytes).
|
|
79
|
+
* @param targetChain - The SVM target chain.
|
|
80
|
+
* @param skipNetworkCheck - Whether to skip deployment status check.
|
|
81
|
+
* @returns The derived 32-byte Solana PDA address (as 0x-prefixed hex) and deployment status.
|
|
82
|
+
*/
|
|
83
|
+
export declare function deriveSvmCeaPda(ueaAddress: `0x${string}`, targetChain: CHAIN, skipNetworkCheck: boolean): DerivedExecutorAccount;
|
|
71
84
|
/**
|
|
72
85
|
* Derive the executor account (UEA or CEA) for a given account.
|
|
73
86
|
*
|
|
@@ -6,6 +6,7 @@ exports.fromChainAgnostic = fromChainAgnostic;
|
|
|
6
6
|
exports.convertOriginToExecutor = convertOriginToExecutor;
|
|
7
7
|
exports.convertExecutorToOriginAccount = convertExecutorToOriginAccount;
|
|
8
8
|
exports.convertExecutorToOrigin = convertExecutorToOrigin;
|
|
9
|
+
exports.deriveSvmCeaPda = deriveSvmCeaPda;
|
|
9
10
|
exports.deriveExecutorAccount = deriveExecutorAccount;
|
|
10
11
|
exports.resolveControllerAccount = resolveControllerAccount;
|
|
11
12
|
const tslib_1 = require("tslib");
|
package/src/lib/utils.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { construct, toUniversal as toUniversalSigner, toUniversalFromKeypair } f
|
|
|
3
3
|
import { CHAIN, PUSH_NETWORK } from './constants/enums';
|
|
4
4
|
import { type MoveableToken } from './constants/tokens';
|
|
5
5
|
import type { PushChain } from './push-chain/push-chain';
|
|
6
|
+
import { registerIdl as registerSvmIdl, getRegisteredIdls as getRegisteredSvmIdls, getIdl as getSvmIdl } from './orchestrator/svm-idl/registry';
|
|
6
7
|
/**
|
|
7
8
|
* @dev - THESE UTILS ARE EXPORTED TO SDK CONSUMER
|
|
8
9
|
* @dev - Make sure each exported fn has good comments to help out sdk consumer
|
|
@@ -32,6 +33,24 @@ export declare class Utils {
|
|
|
32
33
|
deriveExecutorAccount: typeof deriveExecutorAccount;
|
|
33
34
|
resolveControllerAccount: typeof resolveControllerAccount;
|
|
34
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* SVM (Solana) utilities for registering program Anchor IDLs.
|
|
38
|
+
*
|
|
39
|
+
* Register your program's Anchor IDL once per process; `prepareTransaction`
|
|
40
|
+
* then resolves accounts, PDAs, and signers from the IDL so you only need
|
|
41
|
+
* to pass `data` (discriminator + Borsh args), the same shape used for EVM.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* PushChain.utils.svm.registerIdl(
|
|
45
|
+
* PROGRAM_ADDRESS_HEX,
|
|
46
|
+
* testCounterIdl
|
|
47
|
+
* );
|
|
48
|
+
*/
|
|
49
|
+
static svm: {
|
|
50
|
+
registerIdl: typeof registerSvmIdl;
|
|
51
|
+
getRegisteredIdls: typeof getRegisteredSvmIdls;
|
|
52
|
+
getIdl: typeof getSvmIdl;
|
|
53
|
+
};
|
|
35
54
|
static signer: {
|
|
36
55
|
/**
|
|
37
56
|
* Converts various signer types (viem, ethers v6, Solana) into a UniversalSigner.
|
|
@@ -98,7 +117,7 @@ export declare class Utils {
|
|
|
98
117
|
*/
|
|
99
118
|
getChainName: (chainName: string) => string | undefined;
|
|
100
119
|
encodeTxData({ abi, functionName, args, }: {
|
|
101
|
-
abi: any
|
|
120
|
+
abi: any;
|
|
102
121
|
functionName: string;
|
|
103
122
|
args?: any[];
|
|
104
123
|
}): `0x${string}`;
|
package/src/lib/utils.js
CHANGED
|
@@ -7,6 +7,9 @@ const enums_1 = require("./constants/enums");
|
|
|
7
7
|
const tokens_1 = require("./constants/tokens");
|
|
8
8
|
const chain_1 = require("./constants/chain");
|
|
9
9
|
const viem_1 = require("viem");
|
|
10
|
+
const buffer_1 = require("buffer");
|
|
11
|
+
const ix_encoder_1 = require("./orchestrator/svm-idl/ix-encoder");
|
|
12
|
+
const registry_1 = require("./orchestrator/svm-idl/registry");
|
|
10
13
|
/**
|
|
11
14
|
* @dev - THESE UTILS ARE EXPORTED TO SDK CONSUMER
|
|
12
15
|
* @dev - Make sure each exported fn has good comments to help out sdk consumer
|
|
@@ -74,6 +77,24 @@ Utils.account = {
|
|
|
74
77
|
deriveExecutorAccount: account_1.deriveExecutorAccount,
|
|
75
78
|
resolveControllerAccount: account_1.resolveControllerAccount,
|
|
76
79
|
};
|
|
80
|
+
/**
|
|
81
|
+
* SVM (Solana) utilities for registering program Anchor IDLs.
|
|
82
|
+
*
|
|
83
|
+
* Register your program's Anchor IDL once per process; `prepareTransaction`
|
|
84
|
+
* then resolves accounts, PDAs, and signers from the IDL so you only need
|
|
85
|
+
* to pass `data` (discriminator + Borsh args), the same shape used for EVM.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* PushChain.utils.svm.registerIdl(
|
|
89
|
+
* PROGRAM_ADDRESS_HEX,
|
|
90
|
+
* testCounterIdl
|
|
91
|
+
* );
|
|
92
|
+
*/
|
|
93
|
+
Utils.svm = {
|
|
94
|
+
registerIdl: registry_1.registerIdl,
|
|
95
|
+
getRegisteredIdls: registry_1.getRegisteredIdls,
|
|
96
|
+
getIdl: registry_1.getIdl,
|
|
97
|
+
};
|
|
77
98
|
Utils.signer = {
|
|
78
99
|
/**
|
|
79
100
|
* Converts various signer types (viem, ethers v6, Solana) into a UniversalSigner.
|
|
@@ -207,6 +228,13 @@ Utils.helpers = {
|
|
|
207
228
|
};
|
|
208
229
|
})(),
|
|
209
230
|
encodeTxData({ abi, functionName, args = [], }) {
|
|
231
|
+
if ((0, ix_encoder_1.isAnchorIdl)(abi)) {
|
|
232
|
+
if (!Array.isArray(args)) {
|
|
233
|
+
throw new Error('Arguments must be an array');
|
|
234
|
+
}
|
|
235
|
+
const bytes = (0, ix_encoder_1.encodeAnchorIxData)(abi, functionName, args);
|
|
236
|
+
return `0x${buffer_1.Buffer.from(bytes).toString('hex')}`;
|
|
237
|
+
}
|
|
210
238
|
// Validate inputs
|
|
211
239
|
if (!Array.isArray(abi)) {
|
|
212
240
|
throw new Error('ABI must be an array');
|