@panoptic-eng/sdk 1.0.30 → 1.0.32
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/dist/cow/index.js +3 -3
- package/dist/{cow-CSt61vNU.js → cow-CLFJQ-OP.js} +2 -2
- package/dist/{cow-CSt61vNU.js.map → cow-CLFJQ-OP.js.map} +1 -1
- package/dist/{index-B3JZRUNo.d.ts → index-DToj2-Vc.d.ts} +235 -13
- package/dist/index-DToj2-Vc.d.ts.map +1 -0
- package/dist/index.js +2 -2
- package/dist/{irm-IcePQm1r.js → irm-iAI9hTYQ.js} +3 -3
- package/dist/{irm-IcePQm1r.js.map → irm-iAI9hTYQ.js.map} +1 -1
- package/dist/{oracle-BnpPVG8V.d.ts → oracle-DaNTHk7B.d.ts} +14 -1
- package/dist/{oracle-BnpPVG8V.d.ts.map → oracle-DaNTHk7B.d.ts.map} +1 -1
- package/dist/panoptic/v2/index.d.ts +3 -3
- package/dist/panoptic/v2/index.js +5 -5
- package/dist/panoptic/v2/react-public.d.ts +18 -4
- package/dist/panoptic/v2/react-public.d.ts.map +1 -1
- package/dist/panoptic/v2/react-public.js +41 -7
- package/dist/panoptic/v2/react-public.js.map +1 -1
- package/dist/{position-UL1gOvqZ.js → position-ClU7GrTa.js} +44 -12
- package/dist/position-ClU7GrTa.js.map +1 -0
- package/dist/{router-Del9H6e0.js → router-DKFR_vnu.js} +2 -2
- package/dist/{router-Del9H6e0.js.map → router-DKFR_vnu.js.map} +1 -1
- package/dist/{types-VeWdNN0j.d.ts → types-Cy6v8iPf.d.ts} +2 -2
- package/dist/{types-VeWdNN0j.d.ts.map → types-Cy6v8iPf.d.ts.map} +1 -1
- package/dist/uniswap/index.d.ts +2 -2
- package/dist/uniswap/index.js +3 -3
- package/dist/{v2-BSV35bpu.js → v2-DHJxPCAp.js} +465 -167
- package/dist/v2-DHJxPCAp.js.map +1 -0
- package/dist/{writes-RyS0kHpB.js → writes-DQLGdkJ5.js} +50 -26
- package/dist/writes-DQLGdkJ5.js.map +1 -0
- package/package.json +1 -1
- package/dist/index-B3JZRUNo.d.ts.map +0 -1
- package/dist/position-UL1gOvqZ.js.map +0 -1
- package/dist/v2-BSV35bpu.js.map +0 -1
- package/dist/writes-RyS0kHpB.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { formatTokenAmount$1 as formatTokenAmount, getAccountCollateral$1 as getAccountCollateral, panopticQueryAbi
|
|
2
|
-
import { AccountInsolventError$1 as AccountInsolventError, ChunkLimitError$1 as ChunkLimitError, DEFAULT_VEGOID$1 as DEFAULT_VEGOID, InvalidHistoryRangeError$1 as InvalidHistoryRangeError, NotEnoughTokensError$1 as NotEnoughTokensError, PanopticError, PanopticValidationError$1 as PanopticValidationError, StorageDataNotFoundError,
|
|
1
|
+
import { formatTokenAmount$1 as formatTokenAmount, getAccountCollateral$1 as getAccountCollateral, panopticQueryAbi, parseTokenAmount$1 as parseTokenAmount, readBlockAndAggregate, requireReturnData } from "./irm-iAI9hTYQ.js";
|
|
2
|
+
import { AccountInsolventError$1 as AccountInsolventError, ChunkLimitError$1 as ChunkLimitError, DEFAULT_VEGOID$1 as DEFAULT_VEGOID, InvalidHistoryRangeError$1 as InvalidHistoryRangeError, NotEnoughTokensError$1 as NotEnoughTokensError, PanopticError, PanopticValidationError$1 as PanopticValidationError, StorageDataNotFoundError, collateralTrackerV2Abi, decodeLeftRightSigned$1 as decodeLeftRightSigned, decodeLeftRightUnsigned$1 as decodeLeftRightUnsigned, decodePosition, decodePositionBalance, decodeTickSpacing$1 as decodeTickSpacing, getBlockMeta$1 as getBlockMeta, getPool, panopticFactoryV3Abi, panopticFactoryV4Abi, panopticGuardianAbi, panopticPoolV2Abi, panopticQueryAbi$1, parsePanopticError$1 as parsePanopticError, riskEngineAbi, semiFungiblePositionManagerV3Abi, semiFungiblePositionManagerV4Abi, stateViewAbi, uniswapV3PoolAbi } from "./position-ClU7GrTa.js";
|
|
3
3
|
import { MAX_TICK, MAX_TRACKED_CHUNKS, MIN_TICK, WAD, calculatePositionDelta, calculatePositionGamma, calculatePositionValue, priceToTick, sqrtPriceX96ToTick, tickLimits, tickToPrice, tickToPriceDecimalScaled, tickToSqrtPriceX96 } from "./greeks-GysWXct-.js";
|
|
4
|
-
import { addLegToTokenId$1 as addLegToTokenId, buildBatchDispatchArgs$1 as buildBatchDispatchArgs,
|
|
4
|
+
import { addLegToTokenId$1 as addLegToTokenId, buildBatchDispatchArgs$1 as buildBatchDispatchArgs, buildUniqueCredit$1 as buildUniqueCredit, countLegs$1 as countLegs, decodeAllLegs$1 as decodeAllLegs, decodeTokenId$1 as decodeTokenId, getClosedPositionsKey$1 as getClosedPositionsKey, getPendingPositionsKey$1 as getPendingPositionsKey, getPoolMetaKey$1 as getPoolMetaKey, getPositionMetaKey$1 as getPositionMetaKey, getPositionsKey$1 as getPositionsKey, getTrackedChunksKey$1 as getTrackedChunksKey, getTrackedPositionIds$1 as getTrackedPositionIds, jsonSerializer$1 as jsonSerializer, loadCheckpoint$1 as loadCheckpoint, resolveTokenIndex$1 as resolveTokenIndex, simulateOpenPosition$1 as simulateOpenPosition, simulateWithTokenFlow } from "./writes-DQLGdkJ5.js";
|
|
5
5
|
import { ContractFunctionExecutionError, decodeFunctionResult, encodeAbiParameters, encodeFunctionData, getAddress, keccak256, zeroAddress } from "viem";
|
|
6
6
|
import { multicall } from "viem/actions";
|
|
7
7
|
|
|
@@ -1596,6 +1596,35 @@ async function getMaxWithdrawable(params) {
|
|
|
1596
1596
|
};
|
|
1597
1597
|
}
|
|
1598
1598
|
/**
|
|
1599
|
+
* Read the maximum number of shares an account can redeem from a CollateralTracker.
|
|
1600
|
+
*
|
|
1601
|
+
* This is the ERC4626 `maxRedeem(owner)`, i.e. `min(availableShares, balanceOf(owner))`,
|
|
1602
|
+
* and returns 0 when the account has open positions (legs). Redeeming exactly this many
|
|
1603
|
+
* shares burns the account's full (available) share balance, so a MAX withdraw leaves no
|
|
1604
|
+
* rounding dust — unlike an assets-based `withdraw`, which round-trips shares↔assets.
|
|
1605
|
+
*
|
|
1606
|
+
* @param params - The parameters
|
|
1607
|
+
* @returns Maximum redeemable shares with block metadata
|
|
1608
|
+
*/
|
|
1609
|
+
async function getMaxRedeem(params) {
|
|
1610
|
+
const { client, collateralTrackerAddress, account, blockNumber } = params;
|
|
1611
|
+
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
1612
|
+
const [maxRedeem, _meta] = await Promise.all([client.readContract({
|
|
1613
|
+
address: collateralTrackerAddress,
|
|
1614
|
+
abi: collateralTrackerV2Abi,
|
|
1615
|
+
functionName: "maxRedeem",
|
|
1616
|
+
args: [account],
|
|
1617
|
+
blockNumber: targetBlockNumber
|
|
1618
|
+
}), getBlockMeta({
|
|
1619
|
+
client,
|
|
1620
|
+
blockNumber: targetBlockNumber
|
|
1621
|
+
})]);
|
|
1622
|
+
return {
|
|
1623
|
+
maxRedeem,
|
|
1624
|
+
_meta
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1627
|
+
/**
|
|
1599
1628
|
* Try to simulate a solvency-checked withdraw with the given amount.
|
|
1600
1629
|
*/
|
|
1601
1630
|
async function tryWithdrawSimulation(params) {
|
|
@@ -2849,6 +2878,17 @@ const MIN_TICK$1 = -887272n;
|
|
|
2849
2878
|
const MAX_TICK$1 = 887272n;
|
|
2850
2879
|
const FP96 = 1n << 96n;
|
|
2851
2880
|
const Q128$1 = 1n << 128n;
|
|
2881
|
+
/** Cap for a usage ratio with no collateral behind it. */
|
|
2882
|
+
const MAX_USAGE_BPS = 1000000n;
|
|
2883
|
+
const bigintMax = (a, b) => a > b ? a : b;
|
|
2884
|
+
const bigintMin = (a, b) => a < b ? a : b;
|
|
2885
|
+
/**
|
|
2886
|
+
* `RiskEngine.BP_DECREASE_BUFFER` over `PanopticPool.NO_BUFFER` — the extra
|
|
2887
|
+
* margin the solvency check demands at mint (and on collateral withdrawal),
|
|
2888
|
+
* above the maintenance requirement that governs liquidation.
|
|
2889
|
+
*/
|
|
2890
|
+
const MINT_BUFFER = 10666667n;
|
|
2891
|
+
const MINT_BUFFER_DENOMINATOR = 10000000n;
|
|
2852
2892
|
/**
|
|
2853
2893
|
* Convert a token0 amount to its token1-equivalent at the given sqrtPriceX96.
|
|
2854
2894
|
*
|
|
@@ -2960,6 +3000,19 @@ async function getMarginBuffer(params) {
|
|
|
2960
3000
|
]
|
|
2961
3001
|
})
|
|
2962
3002
|
});
|
|
3003
|
+
const checkCollateralIndex = hasPositions ? calls.length : null;
|
|
3004
|
+
if (checkCollateralIndex !== null) calls.push({
|
|
3005
|
+
target: queryAddress,
|
|
3006
|
+
callData: encodeFunctionData({
|
|
3007
|
+
abi: panopticQueryAbi,
|
|
3008
|
+
functionName: "checkCollateral",
|
|
3009
|
+
args: [
|
|
3010
|
+
poolAddress,
|
|
3011
|
+
account,
|
|
3012
|
+
tokenIds
|
|
3013
|
+
]
|
|
3014
|
+
})
|
|
3015
|
+
});
|
|
2963
3016
|
const { _meta, results } = await readBlockAndAggregate({
|
|
2964
3017
|
client,
|
|
2965
3018
|
calls,
|
|
@@ -2991,6 +3044,34 @@ async function getMarginBuffer(params) {
|
|
|
2991
3044
|
functionName: "getLiquidationPrices",
|
|
2992
3045
|
data: requireReturnData(results, liqPricesIndex, "PanopticQuery.getLiquidationPrices")
|
|
2993
3046
|
});
|
|
3047
|
+
const checkCollateralResult = checkCollateralIndex === null ? null : decodeFunctionResult({
|
|
3048
|
+
abi: panopticQueryAbi,
|
|
3049
|
+
functionName: "checkCollateral",
|
|
3050
|
+
data: requireReturnData(results, checkCollateralIndex, "PanopticQuery.checkCollateral")
|
|
3051
|
+
});
|
|
3052
|
+
let usageBps0 = null;
|
|
3053
|
+
let usageBps1 = null;
|
|
3054
|
+
let crossMarginUsageBps = null;
|
|
3055
|
+
let mintableMarginBinding = null;
|
|
3056
|
+
if (checkCollateralResult) {
|
|
3057
|
+
const [balances0, requireds0, balances1, requireds1] = checkCollateralResult;
|
|
3058
|
+
const ratio = (required, balance) => {
|
|
3059
|
+
if (required === void 0 || balance === void 0) return null;
|
|
3060
|
+
if (balance === 0n) return required > 0n ? MAX_USAGE_BPS : 0n;
|
|
3061
|
+
return required * 10000n / balance;
|
|
3062
|
+
};
|
|
3063
|
+
usageBps0 = ratio(requireds0[0], balances0[0]);
|
|
3064
|
+
usageBps1 = ratio(requireds1[0], balances1[0]);
|
|
3065
|
+
if (usageBps0 !== null || usageBps1 !== null) crossMarginUsageBps = usageBps0 === null ? usageBps1 : usageBps1 === null ? usageBps0 : bigintMax(usageBps0, usageBps1);
|
|
3066
|
+
const mintable = (balance, required) => {
|
|
3067
|
+
if (balance === void 0 || required === void 0) return null;
|
|
3068
|
+
const requiredAtMint = (required * MINT_BUFFER + MINT_BUFFER_DENOMINATOR - 1n) / MINT_BUFFER_DENOMINATOR;
|
|
3069
|
+
return balance > requiredAtMint ? balance - requiredAtMint : 0n;
|
|
3070
|
+
};
|
|
3071
|
+
const mintable0 = mintable(balances0[0], requireds0[0]);
|
|
3072
|
+
const mintable1 = mintable(balances1[0], requireds1[0]);
|
|
3073
|
+
if (mintable0 !== null || mintable1 !== null) mintableMarginBinding = mintable0 === null ? mintable1 : mintable1 === null ? mintable0 : bigintMin(mintable0, mintable1);
|
|
3074
|
+
}
|
|
2994
3075
|
let required0Native = 0n;
|
|
2995
3076
|
let required1Native = 0n;
|
|
2996
3077
|
if (positionDataResult) {
|
|
@@ -3039,6 +3120,10 @@ async function getMarginBuffer(params) {
|
|
|
3039
3120
|
liquidationDistance,
|
|
3040
3121
|
lowerLiquidationTick,
|
|
3041
3122
|
upperLiquidationTick,
|
|
3123
|
+
crossMarginUsageBps,
|
|
3124
|
+
usageBps0,
|
|
3125
|
+
usageBps1,
|
|
3126
|
+
mintableMarginBinding,
|
|
3042
3127
|
currentTick,
|
|
3043
3128
|
_meta
|
|
3044
3129
|
};
|
|
@@ -3419,6 +3504,365 @@ async function getAccountBuyingPower(params) {
|
|
|
3419
3504
|
};
|
|
3420
3505
|
}
|
|
3421
3506
|
|
|
3507
|
+
//#endregion
|
|
3508
|
+
//#region src/panoptic/v2/simulations/simulateDispatch.ts
|
|
3509
|
+
/**
|
|
3510
|
+
* Simulate a raw dispatch operation.
|
|
3511
|
+
*
|
|
3512
|
+
* Uses PanopticPool.multicall with getAssetsOf-dispatch-getAssetsOf pattern
|
|
3513
|
+
* to measure exact collateral asset movements.
|
|
3514
|
+
*
|
|
3515
|
+
* @param params - Simulation parameters
|
|
3516
|
+
* @returns Simulation result with dispatch data or error
|
|
3517
|
+
*/
|
|
3518
|
+
async function simulateDispatch(params) {
|
|
3519
|
+
const { client, poolAddress, account, positionIdList, finalPositionIdList, positionSizes, tickAndSpreadLimits, usePremiaAsCollateral = false, builderCode = 0n, blockNumber, existingPositionIdList } = params;
|
|
3520
|
+
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
3521
|
+
const metaPromise = getBlockMeta({
|
|
3522
|
+
client,
|
|
3523
|
+
blockNumber: targetBlockNumber
|
|
3524
|
+
});
|
|
3525
|
+
try {
|
|
3526
|
+
const callData = encodeFunctionData({
|
|
3527
|
+
abi: panopticPoolV2Abi,
|
|
3528
|
+
functionName: "dispatch",
|
|
3529
|
+
args: [
|
|
3530
|
+
positionIdList,
|
|
3531
|
+
finalPositionIdList,
|
|
3532
|
+
positionSizes,
|
|
3533
|
+
tickAndSpreadLimits.map((t) => [
|
|
3534
|
+
Number(t[0]),
|
|
3535
|
+
Number(t[1]),
|
|
3536
|
+
Number(t[2])
|
|
3537
|
+
]),
|
|
3538
|
+
usePremiaAsCollateral,
|
|
3539
|
+
builderCode
|
|
3540
|
+
]
|
|
3541
|
+
});
|
|
3542
|
+
const preFullPositionsCallData = existingPositionIdList !== void 0 ? encodeFunctionData({
|
|
3543
|
+
abi: panopticPoolV2Abi,
|
|
3544
|
+
functionName: "getFullPositionsData",
|
|
3545
|
+
args: [
|
|
3546
|
+
account,
|
|
3547
|
+
false,
|
|
3548
|
+
existingPositionIdList
|
|
3549
|
+
]
|
|
3550
|
+
}) : void 0;
|
|
3551
|
+
const postFullPositionsCallData = encodeFunctionData({
|
|
3552
|
+
abi: panopticPoolV2Abi,
|
|
3553
|
+
functionName: "getFullPositionsData",
|
|
3554
|
+
args: [
|
|
3555
|
+
account,
|
|
3556
|
+
false,
|
|
3557
|
+
finalPositionIdList
|
|
3558
|
+
]
|
|
3559
|
+
});
|
|
3560
|
+
const flowResult = await simulateWithTokenFlow({
|
|
3561
|
+
client,
|
|
3562
|
+
poolAddress,
|
|
3563
|
+
user: account,
|
|
3564
|
+
callData,
|
|
3565
|
+
blockNumber: targetBlockNumber,
|
|
3566
|
+
preCallData: preFullPositionsCallData ? [preFullPositionsCallData] : void 0,
|
|
3567
|
+
postCallData: [postFullPositionsCallData]
|
|
3568
|
+
});
|
|
3569
|
+
if (!flowResult.success || !flowResult.tokenFlow) throw flowResult.rawError ?? new PanopticError(flowResult.error || "Token flow simulation failed");
|
|
3570
|
+
const tokenFlow = flowResult.tokenFlow;
|
|
3571
|
+
const preSnapshot = existingPositionIdList ?? [];
|
|
3572
|
+
const positionsCreated = finalPositionIdList.filter((id) => !preSnapshot.includes(id));
|
|
3573
|
+
const positionsClosed = preSnapshot.filter((id) => !finalPositionIdList.includes(id));
|
|
3574
|
+
const sumCollateralReq = (data$1) => {
|
|
3575
|
+
if (!data$1) return null;
|
|
3576
|
+
try {
|
|
3577
|
+
const decoded = decodeFunctionResult({
|
|
3578
|
+
abi: panopticPoolV2Abi,
|
|
3579
|
+
functionName: "getFullPositionsData",
|
|
3580
|
+
data: data$1
|
|
3581
|
+
});
|
|
3582
|
+
const reqs = decoded[3];
|
|
3583
|
+
let token0 = 0n;
|
|
3584
|
+
let token1 = 0n;
|
|
3585
|
+
for (const packed of reqs) {
|
|
3586
|
+
const r = decodeLeftRightUnsigned(packed);
|
|
3587
|
+
token0 += r.right;
|
|
3588
|
+
token1 += r.left;
|
|
3589
|
+
}
|
|
3590
|
+
return {
|
|
3591
|
+
token0,
|
|
3592
|
+
token1
|
|
3593
|
+
};
|
|
3594
|
+
} catch {
|
|
3595
|
+
return null;
|
|
3596
|
+
}
|
|
3597
|
+
};
|
|
3598
|
+
const preReq = sumCollateralReq(flowResult.preCallResults?.[0]);
|
|
3599
|
+
const postReq = sumCollateralReq(flowResult.postCallResults?.[0]);
|
|
3600
|
+
const _meta = await metaPromise;
|
|
3601
|
+
const data = {
|
|
3602
|
+
netAmount0: tokenFlow.delta0,
|
|
3603
|
+
netAmount1: tokenFlow.delta1,
|
|
3604
|
+
positionsCreated,
|
|
3605
|
+
positionsClosed,
|
|
3606
|
+
postCollateral0: tokenFlow.balanceAfter0,
|
|
3607
|
+
postCollateral1: tokenFlow.balanceAfter1,
|
|
3608
|
+
preMarginExcess0: preReq ? tokenFlow.balanceBefore0 - preReq.token0 : null,
|
|
3609
|
+
preMarginExcess1: preReq ? tokenFlow.balanceBefore1 - preReq.token1 : null,
|
|
3610
|
+
postMarginExcess0: postReq ? tokenFlow.balanceAfter0 - postReq.token0 : null,
|
|
3611
|
+
postMarginExcess1: postReq ? tokenFlow.balanceAfter1 - postReq.token1 : null
|
|
3612
|
+
};
|
|
3613
|
+
return {
|
|
3614
|
+
success: true,
|
|
3615
|
+
data,
|
|
3616
|
+
gasEstimate: flowResult.gasEstimate,
|
|
3617
|
+
tokenFlow,
|
|
3618
|
+
_meta
|
|
3619
|
+
};
|
|
3620
|
+
} catch (error) {
|
|
3621
|
+
const _meta = await metaPromise;
|
|
3622
|
+
return {
|
|
3623
|
+
success: false,
|
|
3624
|
+
error: error instanceof PanopticError ? error : new PanopticError(error instanceof Error ? error.message : "Simulation failed", error instanceof Error ? error : void 0),
|
|
3625
|
+
_meta
|
|
3626
|
+
};
|
|
3627
|
+
}
|
|
3628
|
+
}
|
|
3629
|
+
|
|
3630
|
+
//#endregion
|
|
3631
|
+
//#region src/panoptic/v2/simulations/tokenShortfallRecovery.ts
|
|
3632
|
+
const BPS_DENOMINATOR = 10000n;
|
|
3633
|
+
const MAX_RECOVERY_QUOTE_ATTEMPTS = 8;
|
|
3634
|
+
/**
|
|
3635
|
+
* Wrap a dispatch with a temporary credit leg that sources the shortfall.
|
|
3636
|
+
*
|
|
3637
|
+
* Exact-output construction: mint the credit with `swapAtMint=true` (paying a
|
|
3638
|
+
* swapped amount of the token the account has), run the user's operations, then
|
|
3639
|
+
* burn it with `swapAtMint=false` to receive exactly the missing token.
|
|
3640
|
+
*
|
|
3641
|
+
* A credit rather than a loan so the recovery is never capped by the shortfall
|
|
3642
|
+
* token's utilization — the case that fails today on a >94% utilized tracker.
|
|
3643
|
+
*/
|
|
3644
|
+
function buildTokenShortfallRecoveryDispatch(params) {
|
|
3645
|
+
const { dispatch, creditTokenId, creditPositionSize, tickLimitLow, tickLimitHigh } = params;
|
|
3646
|
+
const low = tickLimitLow <= tickLimitHigh ? tickLimitLow : tickLimitHigh;
|
|
3647
|
+
const high = tickLimitLow <= tickLimitHigh ? tickLimitHigh : tickLimitLow;
|
|
3648
|
+
const mintLimits = [
|
|
3649
|
+
high,
|
|
3650
|
+
low,
|
|
3651
|
+
0n
|
|
3652
|
+
];
|
|
3653
|
+
const burnLimits = [
|
|
3654
|
+
low,
|
|
3655
|
+
high,
|
|
3656
|
+
0n
|
|
3657
|
+
];
|
|
3658
|
+
return {
|
|
3659
|
+
positionIdList: [
|
|
3660
|
+
creditTokenId,
|
|
3661
|
+
...dispatch.positionIdList,
|
|
3662
|
+
creditTokenId
|
|
3663
|
+
],
|
|
3664
|
+
finalPositionIdList: [...dispatch.finalPositionIdList],
|
|
3665
|
+
positionSizes: [
|
|
3666
|
+
creditPositionSize,
|
|
3667
|
+
...dispatch.positionSizes,
|
|
3668
|
+
0n
|
|
3669
|
+
],
|
|
3670
|
+
tickAndSpreadLimits: [
|
|
3671
|
+
mintLimits,
|
|
3672
|
+
...dispatch.tickAndSpreadLimits,
|
|
3673
|
+
burnLimits
|
|
3674
|
+
],
|
|
3675
|
+
usePremiaAsCollateral: dispatch.usePremiaAsCollateral,
|
|
3676
|
+
builderCode: dispatch.builderCode
|
|
3677
|
+
};
|
|
3678
|
+
}
|
|
3679
|
+
/**
|
|
3680
|
+
* Extract a fully-decoded `NotEnoughTokens` revert from an arbitrary error.
|
|
3681
|
+
*
|
|
3682
|
+
* Returns `null` when the error is something else, or when only the 4-byte
|
|
3683
|
+
* selector could be matched (the parser's fallback path constructs the error
|
|
3684
|
+
* with undefined args, which is not actionable).
|
|
3685
|
+
*/
|
|
3686
|
+
function getNotEnoughTokensError(error) {
|
|
3687
|
+
let candidate = null;
|
|
3688
|
+
if (error instanceof NotEnoughTokensError) candidate = error;
|
|
3689
|
+
else {
|
|
3690
|
+
const parsed = parsePanopticError(error);
|
|
3691
|
+
if (parsed?.error instanceof NotEnoughTokensError) candidate = parsed.error;
|
|
3692
|
+
}
|
|
3693
|
+
if (candidate === null) return null;
|
|
3694
|
+
const args = candidate;
|
|
3695
|
+
if (args.tokenAddress === void 0 || args.assetsRequested === void 0 || args.assetBalance === void 0) return null;
|
|
3696
|
+
return candidate;
|
|
3697
|
+
}
|
|
3698
|
+
function maximumAmountIn(estimatedAmountIn, slippageBps) {
|
|
3699
|
+
if (slippageBps < 0n) throw new PanopticError("slippageBps must be non-negative");
|
|
3700
|
+
return (estimatedAmountIn * (BPS_DENOMINATOR + slippageBps) + BPS_DENOMINATOR - 1n) / BPS_DENOMINATOR;
|
|
3701
|
+
}
|
|
3702
|
+
function getInputAmount(tokenFlow, tokenInIndex) {
|
|
3703
|
+
const delta = tokenInIndex === 0n ? tokenFlow.delta0 : tokenFlow.delta1;
|
|
3704
|
+
return delta < 0n ? -delta : delta;
|
|
3705
|
+
}
|
|
3706
|
+
function getBalanceBefore(tokenFlow, tokenIndex) {
|
|
3707
|
+
return tokenIndex === 0n ? tokenFlow.balanceBefore0 : tokenFlow.balanceBefore1;
|
|
3708
|
+
}
|
|
3709
|
+
function getOutputAmount(tokenFlow, tokenOutIndex) {
|
|
3710
|
+
const delta = tokenOutIndex === 0n ? tokenFlow.delta0 : tokenFlow.delta1;
|
|
3711
|
+
return delta > 0n ? delta : 0n;
|
|
3712
|
+
}
|
|
3713
|
+
async function quoteTokenShortfallRecovery(params) {
|
|
3714
|
+
const shortfallError = getNotEnoughTokensError(params.error);
|
|
3715
|
+
if (shortfallError === null) return {
|
|
3716
|
+
available: false,
|
|
3717
|
+
reason: "not-token-shortfall"
|
|
3718
|
+
};
|
|
3719
|
+
let amountOut = shortfallError.assetsRequested - shortfallError.assetBalance;
|
|
3720
|
+
if (amountOut <= 0n) return {
|
|
3721
|
+
available: false,
|
|
3722
|
+
reason: "invalid-shortfall",
|
|
3723
|
+
detail: `requested=${shortfallError.assetsRequested} <= balance=${shortfallError.assetBalance}`
|
|
3724
|
+
};
|
|
3725
|
+
if (params.slippageBps < 0n || params.slippageBps > BPS_DENOMINATOR) return {
|
|
3726
|
+
available: false,
|
|
3727
|
+
reason: "invalid-slippage",
|
|
3728
|
+
detail: `slippageBps=${params.slippageBps} is outside [0, ${BPS_DENOMINATOR}]`
|
|
3729
|
+
};
|
|
3730
|
+
const tickLimitLow = params.tickLimitLow ?? MIN_TICK;
|
|
3731
|
+
const tickLimitHigh = params.tickLimitHigh ?? MAX_TICK;
|
|
3732
|
+
if (tickLimitLow >= tickLimitHigh) return {
|
|
3733
|
+
available: false,
|
|
3734
|
+
reason: "invalid-tick-limits",
|
|
3735
|
+
detail: `tickLimitLow=${tickLimitLow} >= tickLimitHigh=${tickLimitHigh}`
|
|
3736
|
+
};
|
|
3737
|
+
const targetBlockNumber = params.blockNumber ?? await params.client.getBlockNumber();
|
|
3738
|
+
const pool = await getPool({
|
|
3739
|
+
client: params.client,
|
|
3740
|
+
poolAddress: params.poolAddress,
|
|
3741
|
+
chainId: params.chainId,
|
|
3742
|
+
blockNumber: targetBlockNumber
|
|
3743
|
+
});
|
|
3744
|
+
const token0 = pool.collateralTracker0.token;
|
|
3745
|
+
const token1 = pool.collateralTracker1.token;
|
|
3746
|
+
const normalizedShortfallToken = shortfallError.tokenAddress.toLowerCase();
|
|
3747
|
+
const isToken0Shortfall = normalizedShortfallToken === token0.toLowerCase() || normalizedShortfallToken === pool.collateralTracker0.address.toLowerCase();
|
|
3748
|
+
const isToken1Shortfall = normalizedShortfallToken === token1.toLowerCase() || normalizedShortfallToken === pool.collateralTracker1.address.toLowerCase();
|
|
3749
|
+
const tokenOutIndex = isToken0Shortfall ? 0n : isToken1Shortfall ? 1n : null;
|
|
3750
|
+
if (tokenOutIndex === null) return {
|
|
3751
|
+
available: false,
|
|
3752
|
+
reason: "unsupported-token",
|
|
3753
|
+
detail: `${shortfallError.tokenAddress} is neither collateral token of ${params.poolAddress}`
|
|
3754
|
+
};
|
|
3755
|
+
const tokenInIndex = tokenOutIndex === 0n ? 1n : 0n;
|
|
3756
|
+
const tokenOut = tokenOutIndex === 0n ? token0 : token1;
|
|
3757
|
+
const tokenIn = tokenInIndex === 0n ? token0 : token1;
|
|
3758
|
+
const collisionIds = Array.from(new Set([
|
|
3759
|
+
...params.existingPositionIds,
|
|
3760
|
+
...params.dispatch.positionIdList,
|
|
3761
|
+
...params.dispatch.finalPositionIdList
|
|
3762
|
+
]));
|
|
3763
|
+
for (let attempt = 0; attempt < MAX_RECOVERY_QUOTE_ATTEMPTS; attempt++) {
|
|
3764
|
+
const credit = buildUniqueCredit(pool.poolId, tokenOutIndex, tokenOutIndex, pool.currentTick, pool.tickSpacing, collisionIds, amountOut);
|
|
3765
|
+
const recoveredDispatch = buildTokenShortfallRecoveryDispatch({
|
|
3766
|
+
dispatch: params.dispatch,
|
|
3767
|
+
creditTokenId: credit.tokenId,
|
|
3768
|
+
creditPositionSize: credit.adjustedSize,
|
|
3769
|
+
tickLimitLow,
|
|
3770
|
+
tickLimitHigh
|
|
3771
|
+
});
|
|
3772
|
+
const swapDispatch = buildTokenShortfallRecoveryDispatch({
|
|
3773
|
+
dispatch: {
|
|
3774
|
+
positionIdList: [],
|
|
3775
|
+
finalPositionIdList: [...params.existingPositionIds],
|
|
3776
|
+
positionSizes: [],
|
|
3777
|
+
tickAndSpreadLimits: [],
|
|
3778
|
+
usePremiaAsCollateral: false,
|
|
3779
|
+
builderCode: 0n
|
|
3780
|
+
},
|
|
3781
|
+
creditTokenId: credit.tokenId,
|
|
3782
|
+
creditPositionSize: credit.adjustedSize,
|
|
3783
|
+
tickLimitLow,
|
|
3784
|
+
tickLimitHigh
|
|
3785
|
+
});
|
|
3786
|
+
const swapSimulation = await simulateDispatch({
|
|
3787
|
+
client: params.client,
|
|
3788
|
+
poolAddress: params.poolAddress,
|
|
3789
|
+
account: params.account,
|
|
3790
|
+
existingPositionIdList: params.existingPositionIds,
|
|
3791
|
+
...swapDispatch,
|
|
3792
|
+
blockNumber: targetBlockNumber
|
|
3793
|
+
});
|
|
3794
|
+
if (!swapSimulation.success || swapSimulation.tokenFlow === void 0) return {
|
|
3795
|
+
available: false,
|
|
3796
|
+
reason: "swap-unavailable",
|
|
3797
|
+
detail: swapSimulation.success ? "swap-only simulation returned no token flow" : `swap-only simulation reverted: ${swapSimulation.error.message}`,
|
|
3798
|
+
error: swapSimulation.success ? void 0 : swapSimulation.error
|
|
3799
|
+
};
|
|
3800
|
+
const estimatedAmountIn = getInputAmount(swapSimulation.tokenFlow, tokenInIndex);
|
|
3801
|
+
const maxAmountIn = maximumAmountIn(estimatedAmountIn, params.slippageBps);
|
|
3802
|
+
const swapOutput = getOutputAmount(swapSimulation.tokenFlow, tokenOutIndex);
|
|
3803
|
+
const sourceBalance = getBalanceBefore(swapSimulation.tokenFlow, tokenInIndex);
|
|
3804
|
+
if (swapOutput < amountOut || sourceBalance < maxAmountIn) return {
|
|
3805
|
+
available: false,
|
|
3806
|
+
reason: "swap-unavailable",
|
|
3807
|
+
detail: swapOutput < amountOut ? `swap output ${swapOutput} < required ${amountOut}` : `source balance ${sourceBalance} < maximumAmountIn ${maxAmountIn} (estimated ${estimatedAmountIn}, slippageBps ${params.slippageBps})`,
|
|
3808
|
+
error: new PanopticError("Insufficient source collateral for the recovery swap")
|
|
3809
|
+
};
|
|
3810
|
+
const recoverySimulation = await simulateDispatch({
|
|
3811
|
+
client: params.client,
|
|
3812
|
+
poolAddress: params.poolAddress,
|
|
3813
|
+
account: params.account,
|
|
3814
|
+
existingPositionIdList: params.existingPositionIds,
|
|
3815
|
+
...recoveredDispatch,
|
|
3816
|
+
blockNumber: targetBlockNumber
|
|
3817
|
+
});
|
|
3818
|
+
if (recoverySimulation.success) {
|
|
3819
|
+
if (recoverySimulation.tokenFlow !== void 0) return {
|
|
3820
|
+
available: true,
|
|
3821
|
+
quote: {
|
|
3822
|
+
tokenIn,
|
|
3823
|
+
tokenOut,
|
|
3824
|
+
amountOut,
|
|
3825
|
+
estimatedAmountIn,
|
|
3826
|
+
maximumAmountIn: maxAmountIn,
|
|
3827
|
+
slippageBps: params.slippageBps,
|
|
3828
|
+
netTokenInChange: tokenInIndex === 0n ? recoverySimulation.tokenFlow.delta0 : recoverySimulation.tokenFlow.delta1,
|
|
3829
|
+
netTokenOutChange: tokenOutIndex === 0n ? recoverySimulation.tokenFlow.delta0 : recoverySimulation.tokenFlow.delta1,
|
|
3830
|
+
creditTokenId: credit.tokenId,
|
|
3831
|
+
dispatch: recoveredDispatch,
|
|
3832
|
+
simulation: {
|
|
3833
|
+
...recoverySimulation,
|
|
3834
|
+
tokenFlow: recoverySimulation.tokenFlow
|
|
3835
|
+
},
|
|
3836
|
+
tokenFlow: recoverySimulation.tokenFlow,
|
|
3837
|
+
_meta: recoverySimulation._meta
|
|
3838
|
+
}
|
|
3839
|
+
};
|
|
3840
|
+
return {
|
|
3841
|
+
available: false,
|
|
3842
|
+
reason: "recovery-unavailable",
|
|
3843
|
+
detail: "wrapped dispatch simulation returned no token flow",
|
|
3844
|
+
error: new PanopticError("Recovery simulation did not return token flow")
|
|
3845
|
+
};
|
|
3846
|
+
}
|
|
3847
|
+
const remainingShortfall = getNotEnoughTokensError(recoverySimulation.error);
|
|
3848
|
+
if (remainingShortfall === null || remainingShortfall.tokenAddress.toLowerCase() !== normalizedShortfallToken) return {
|
|
3849
|
+
available: false,
|
|
3850
|
+
reason: "recovery-unavailable",
|
|
3851
|
+
detail: `wrapped dispatch reverted with a non-shortfall error: ${recoverySimulation.error.message}`,
|
|
3852
|
+
error: recoverySimulation.error
|
|
3853
|
+
};
|
|
3854
|
+
const decodedShortfall = remainingShortfall.assetsRequested - remainingShortfall.assetBalance;
|
|
3855
|
+
const additionalAmountOut = decodedShortfall > 0n ? decodedShortfall : amountOut;
|
|
3856
|
+
amountOut += additionalAmountOut;
|
|
3857
|
+
}
|
|
3858
|
+
return {
|
|
3859
|
+
available: false,
|
|
3860
|
+
reason: "recovery-unavailable",
|
|
3861
|
+
detail: `still short after ${MAX_RECOVERY_QUOTE_ATTEMPTS} sizing attempts (last target ${amountOut})`,
|
|
3862
|
+
error: new PanopticError("Could not cover recovery swap costs within the quote attempt limit")
|
|
3863
|
+
};
|
|
3864
|
+
}
|
|
3865
|
+
|
|
3422
3866
|
//#endregion
|
|
3423
3867
|
//#region src/panoptic/v2/reads/openPositionPreview.ts
|
|
3424
3868
|
/**
|
|
@@ -3456,16 +3900,19 @@ async function getOpenPositionPreview(params) {
|
|
|
3456
3900
|
blockNumber
|
|
3457
3901
|
})]);
|
|
3458
3902
|
let isSolvent = true;
|
|
3903
|
+
let tokenShortfall = null;
|
|
3459
3904
|
if (!simulation.success) {
|
|
3460
3905
|
const parsed = parsePanopticError(simulation.error);
|
|
3461
3906
|
const err = parsed?.error ?? simulation.error;
|
|
3462
|
-
isSolvent = !(err instanceof AccountInsolventError
|
|
3907
|
+
isSolvent = !(err instanceof AccountInsolventError);
|
|
3908
|
+
tokenShortfall = getNotEnoughTokensError(err);
|
|
3463
3909
|
}
|
|
3464
3910
|
const data = simulation.success ? simulation.data : null;
|
|
3465
3911
|
return {
|
|
3466
3912
|
currentBuyingPower,
|
|
3467
3913
|
simulation,
|
|
3468
3914
|
isSolvent,
|
|
3915
|
+
tokenShortfall,
|
|
3469
3916
|
amount0Required: data?.amount0Required ?? null,
|
|
3470
3917
|
amount1Required: data?.amount1Required ?? null,
|
|
3471
3918
|
postCollateral0: data?.postCollateral0 ?? null,
|
|
@@ -4102,6 +4549,7 @@ async function getUniswapV4PoolBasicState(params) {
|
|
|
4102
4549
|
poolId,
|
|
4103
4550
|
sqrtPriceX96: slot0[0],
|
|
4104
4551
|
currentTick: Number(slot0[1]),
|
|
4552
|
+
protocolFee: BigInt(slot0[2]),
|
|
4105
4553
|
lpFee: Number(slot0[3]),
|
|
4106
4554
|
liquidity,
|
|
4107
4555
|
_meta
|
|
@@ -4187,6 +4635,7 @@ async function getUniswapV4PoolInfo(params) {
|
|
|
4187
4635
|
hooks: poolKey.hooks,
|
|
4188
4636
|
currentTick: Number(slot0[1]),
|
|
4189
4637
|
sqrtPriceX96: slot0[0],
|
|
4638
|
+
protocolFee: BigInt(slot0[2]),
|
|
4190
4639
|
liquidity,
|
|
4191
4640
|
_meta
|
|
4192
4641
|
};
|
|
@@ -5214,129 +5663,6 @@ async function getPoolDeploymentBlock(client, poolAddress) {
|
|
|
5214
5663
|
return foundBlock;
|
|
5215
5664
|
}
|
|
5216
5665
|
|
|
5217
|
-
//#endregion
|
|
5218
|
-
//#region src/panoptic/v2/simulations/simulateDispatch.ts
|
|
5219
|
-
/**
|
|
5220
|
-
* Simulate a raw dispatch operation.
|
|
5221
|
-
*
|
|
5222
|
-
* Uses PanopticPool.multicall with getAssetsOf-dispatch-getAssetsOf pattern
|
|
5223
|
-
* to measure exact collateral asset movements.
|
|
5224
|
-
*
|
|
5225
|
-
* @param params - Simulation parameters
|
|
5226
|
-
* @returns Simulation result with dispatch data or error
|
|
5227
|
-
*/
|
|
5228
|
-
async function simulateDispatch(params) {
|
|
5229
|
-
const { client, poolAddress, account, positionIdList, finalPositionIdList, positionSizes, tickAndSpreadLimits, usePremiaAsCollateral = false, builderCode = 0n, blockNumber, existingPositionIdList } = params;
|
|
5230
|
-
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
5231
|
-
const metaPromise = getBlockMeta({
|
|
5232
|
-
client,
|
|
5233
|
-
blockNumber: targetBlockNumber
|
|
5234
|
-
});
|
|
5235
|
-
try {
|
|
5236
|
-
const callData = encodeFunctionData({
|
|
5237
|
-
abi: panopticPoolV2Abi,
|
|
5238
|
-
functionName: "dispatch",
|
|
5239
|
-
args: [
|
|
5240
|
-
positionIdList,
|
|
5241
|
-
finalPositionIdList,
|
|
5242
|
-
positionSizes,
|
|
5243
|
-
tickAndSpreadLimits.map((t) => [
|
|
5244
|
-
Number(t[0]),
|
|
5245
|
-
Number(t[1]),
|
|
5246
|
-
Number(t[2])
|
|
5247
|
-
]),
|
|
5248
|
-
usePremiaAsCollateral,
|
|
5249
|
-
builderCode
|
|
5250
|
-
]
|
|
5251
|
-
});
|
|
5252
|
-
const preFullPositionsCallData = existingPositionIdList !== void 0 ? encodeFunctionData({
|
|
5253
|
-
abi: panopticPoolV2Abi,
|
|
5254
|
-
functionName: "getFullPositionsData",
|
|
5255
|
-
args: [
|
|
5256
|
-
account,
|
|
5257
|
-
false,
|
|
5258
|
-
existingPositionIdList
|
|
5259
|
-
]
|
|
5260
|
-
}) : void 0;
|
|
5261
|
-
const postFullPositionsCallData = encodeFunctionData({
|
|
5262
|
-
abi: panopticPoolV2Abi,
|
|
5263
|
-
functionName: "getFullPositionsData",
|
|
5264
|
-
args: [
|
|
5265
|
-
account,
|
|
5266
|
-
false,
|
|
5267
|
-
finalPositionIdList
|
|
5268
|
-
]
|
|
5269
|
-
});
|
|
5270
|
-
const flowResult = await simulateWithTokenFlow({
|
|
5271
|
-
client,
|
|
5272
|
-
poolAddress,
|
|
5273
|
-
user: account,
|
|
5274
|
-
callData,
|
|
5275
|
-
blockNumber: targetBlockNumber,
|
|
5276
|
-
preCallData: preFullPositionsCallData ? [preFullPositionsCallData] : void 0,
|
|
5277
|
-
postCallData: [postFullPositionsCallData]
|
|
5278
|
-
});
|
|
5279
|
-
if (!flowResult.success || !flowResult.tokenFlow) throw flowResult.rawError ?? new PanopticError(flowResult.error || "Token flow simulation failed");
|
|
5280
|
-
const tokenFlow = flowResult.tokenFlow;
|
|
5281
|
-
const preSnapshot = existingPositionIdList ?? [];
|
|
5282
|
-
const positionsCreated = finalPositionIdList.filter((id) => !preSnapshot.includes(id));
|
|
5283
|
-
const positionsClosed = preSnapshot.filter((id) => !finalPositionIdList.includes(id));
|
|
5284
|
-
const sumCollateralReq = (data$1) => {
|
|
5285
|
-
if (!data$1) return null;
|
|
5286
|
-
try {
|
|
5287
|
-
const decoded = decodeFunctionResult({
|
|
5288
|
-
abi: panopticPoolV2Abi,
|
|
5289
|
-
functionName: "getFullPositionsData",
|
|
5290
|
-
data: data$1
|
|
5291
|
-
});
|
|
5292
|
-
const reqs = decoded[3];
|
|
5293
|
-
let token0 = 0n;
|
|
5294
|
-
let token1 = 0n;
|
|
5295
|
-
for (const packed of reqs) {
|
|
5296
|
-
const r = decodeLeftRightUnsigned(packed);
|
|
5297
|
-
token0 += r.right;
|
|
5298
|
-
token1 += r.left;
|
|
5299
|
-
}
|
|
5300
|
-
return {
|
|
5301
|
-
token0,
|
|
5302
|
-
token1
|
|
5303
|
-
};
|
|
5304
|
-
} catch {
|
|
5305
|
-
return null;
|
|
5306
|
-
}
|
|
5307
|
-
};
|
|
5308
|
-
const preReq = sumCollateralReq(flowResult.preCallResults?.[0]);
|
|
5309
|
-
const postReq = sumCollateralReq(flowResult.postCallResults?.[0]);
|
|
5310
|
-
const _meta = await metaPromise;
|
|
5311
|
-
const data = {
|
|
5312
|
-
netAmount0: tokenFlow.delta0,
|
|
5313
|
-
netAmount1: tokenFlow.delta1,
|
|
5314
|
-
positionsCreated,
|
|
5315
|
-
positionsClosed,
|
|
5316
|
-
postCollateral0: tokenFlow.balanceAfter0,
|
|
5317
|
-
postCollateral1: tokenFlow.balanceAfter1,
|
|
5318
|
-
preMarginExcess0: preReq ? tokenFlow.balanceBefore0 - preReq.token0 : null,
|
|
5319
|
-
preMarginExcess1: preReq ? tokenFlow.balanceBefore1 - preReq.token1 : null,
|
|
5320
|
-
postMarginExcess0: postReq ? tokenFlow.balanceAfter0 - postReq.token0 : null,
|
|
5321
|
-
postMarginExcess1: postReq ? tokenFlow.balanceAfter1 - postReq.token1 : null
|
|
5322
|
-
};
|
|
5323
|
-
return {
|
|
5324
|
-
success: true,
|
|
5325
|
-
data,
|
|
5326
|
-
gasEstimate: flowResult.gasEstimate,
|
|
5327
|
-
tokenFlow,
|
|
5328
|
-
_meta
|
|
5329
|
-
};
|
|
5330
|
-
} catch (error) {
|
|
5331
|
-
const _meta = await metaPromise;
|
|
5332
|
-
return {
|
|
5333
|
-
success: false,
|
|
5334
|
-
error: error instanceof PanopticError ? error : new PanopticError(error instanceof Error ? error.message : "Simulation failed", error instanceof Error ? error : void 0),
|
|
5335
|
-
_meta
|
|
5336
|
-
};
|
|
5337
|
-
}
|
|
5338
|
-
}
|
|
5339
|
-
|
|
5340
5666
|
//#endregion
|
|
5341
5667
|
//#region src/panoptic/v2/simulations/simulateBatchDispatch.ts
|
|
5342
5668
|
/**
|
|
@@ -6103,47 +6429,19 @@ async function simulateSFPMBurn(params) {
|
|
|
6103
6429
|
//#endregion
|
|
6104
6430
|
//#region src/panoptic/v2/simulations/simulateSwap.ts
|
|
6105
6431
|
/**
|
|
6106
|
-
* Resolve token index, throwing SwapTokenMismatchError on mismatch.
|
|
6107
|
-
*/
|
|
6108
|
-
function resolveTokenIndex(tokenAddress, token0, token1) {
|
|
6109
|
-
const lower = tokenAddress.toLowerCase();
|
|
6110
|
-
if (lower === token0.toLowerCase()) return 0n;
|
|
6111
|
-
if (lower === token1.toLowerCase()) return 1n;
|
|
6112
|
-
throw new SwapTokenMismatchError(tokenAddress, token0, token1);
|
|
6113
|
-
}
|
|
6114
|
-
/**
|
|
6115
|
-
* Build a unique loan tokenId.
|
|
6116
|
-
*/
|
|
6117
|
-
function buildUniqueLoan(poolId, asset, tokenType, currentTick, tickSpacing, existingPositionIds) {
|
|
6118
|
-
const mod = currentTick % tickSpacing;
|
|
6119
|
-
let strike = currentTick - (mod + tickSpacing) % tickSpacing;
|
|
6120
|
-
const step = tickSpacing;
|
|
6121
|
-
const existingSet = new Set(existingPositionIds);
|
|
6122
|
-
for (let attempt = 0; attempt < 1e3; attempt++) {
|
|
6123
|
-
const tokenId = createTokenIdBuilder(poolId).addLoan({
|
|
6124
|
-
asset,
|
|
6125
|
-
tokenType,
|
|
6126
|
-
strike
|
|
6127
|
-
}).build();
|
|
6128
|
-
if (!existingSet.has(tokenId)) return tokenId;
|
|
6129
|
-
strike += step;
|
|
6130
|
-
}
|
|
6131
|
-
throw new PanopticError("Could not build unique loan tokenId after 1000 attempts");
|
|
6132
|
-
}
|
|
6133
|
-
/**
|
|
6134
6432
|
* Build dispatch calldata for swap simulation.
|
|
6135
6433
|
*/
|
|
6136
|
-
function buildSwapCallData(
|
|
6434
|
+
function buildSwapCallData(creditTokenId, existingPositionIds, amount, mintTickLimits, burnTickLimits, builderCode) {
|
|
6137
6435
|
return encodeFunctionData({
|
|
6138
6436
|
abi: panopticPoolV2Abi,
|
|
6139
6437
|
functionName: "dispatch",
|
|
6140
6438
|
args: [
|
|
6141
|
-
[
|
|
6439
|
+
[creditTokenId, creditTokenId],
|
|
6142
6440
|
[...existingPositionIds],
|
|
6143
6441
|
[amount, 0n],
|
|
6144
6442
|
[mintTickLimits, burnTickLimits],
|
|
6145
6443
|
false,
|
|
6146
|
-
|
|
6444
|
+
builderCode
|
|
6147
6445
|
]
|
|
6148
6446
|
});
|
|
6149
6447
|
}
|
|
@@ -6171,7 +6469,7 @@ function buildSwapResult(tokenFlow, tokenOutIndex) {
|
|
|
6171
6469
|
* @returns Simulation result with swap data or error
|
|
6172
6470
|
*/
|
|
6173
6471
|
async function simulateSwapExactOut(params) {
|
|
6174
|
-
const { client, poolAddress, account, chainId, tokenOut, amountOut, slippageBps, existingPositionIds, blockNumber } = params;
|
|
6472
|
+
const { client, poolAddress, account, chainId, tokenOut, amountOut, slippageBps, existingPositionIds, builderCode = 0n, blockNumber } = params;
|
|
6175
6473
|
try {
|
|
6176
6474
|
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
6177
6475
|
const metaPromise = getBlockMeta({
|
|
@@ -6187,9 +6485,9 @@ async function simulateSwapExactOut(params) {
|
|
|
6187
6485
|
const token0 = pool.collateralTracker0.token;
|
|
6188
6486
|
const token1 = pool.collateralTracker1.token;
|
|
6189
6487
|
const tokenOutIndex = resolveTokenIndex(tokenOut, token0, token1);
|
|
6190
|
-
const tokenType = tokenOutIndex
|
|
6488
|
+
const tokenType = tokenOutIndex;
|
|
6191
6489
|
const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps);
|
|
6192
|
-
const
|
|
6490
|
+
const { tokenId: creditTokenId, adjustedSize } = buildUniqueCredit(pool.poolId, tokenOutIndex, tokenType, pool.currentTick, pool.tickSpacing, existingPositionIds, amountOut);
|
|
6193
6491
|
const mintTickLimits = [
|
|
6194
6492
|
Number(tickLimitHigh),
|
|
6195
6493
|
Number(tickLimitLow),
|
|
@@ -6200,7 +6498,7 @@ async function simulateSwapExactOut(params) {
|
|
|
6200
6498
|
Number(tickLimitHigh),
|
|
6201
6499
|
0
|
|
6202
6500
|
];
|
|
6203
|
-
const callData = buildSwapCallData(
|
|
6501
|
+
const callData = buildSwapCallData(creditTokenId, existingPositionIds, adjustedSize, mintTickLimits, burnTickLimits, builderCode);
|
|
6204
6502
|
const flowResult = await simulateWithTokenFlow({
|
|
6205
6503
|
client,
|
|
6206
6504
|
poolAddress,
|
|
@@ -6238,7 +6536,7 @@ async function simulateSwapExactOut(params) {
|
|
|
6238
6536
|
* @returns Simulation result with swap data or error
|
|
6239
6537
|
*/
|
|
6240
6538
|
async function simulateSwapExactIn(params) {
|
|
6241
|
-
const { client, poolAddress, account, chainId, tokenIn, amountIn, slippageBps, existingPositionIds, blockNumber } = params;
|
|
6539
|
+
const { client, poolAddress, account, chainId, tokenIn, amountIn, slippageBps, existingPositionIds, builderCode = 0n, blockNumber } = params;
|
|
6242
6540
|
try {
|
|
6243
6541
|
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
6244
6542
|
const metaPromise = getBlockMeta({
|
|
@@ -6256,7 +6554,7 @@ async function simulateSwapExactIn(params) {
|
|
|
6256
6554
|
const tokenInIndex = resolveTokenIndex(tokenIn, token0, token1);
|
|
6257
6555
|
const tokenType = tokenInIndex;
|
|
6258
6556
|
const { low: tickLimitLow, high: tickLimitHigh } = tickLimits(pool.currentTick, slippageBps);
|
|
6259
|
-
const
|
|
6557
|
+
const { tokenId: creditTokenId, adjustedSize } = buildUniqueCredit(pool.poolId, tokenInIndex, tokenType, pool.currentTick, pool.tickSpacing, existingPositionIds, amountIn);
|
|
6260
6558
|
const mintTickLimits = [
|
|
6261
6559
|
Number(tickLimitLow),
|
|
6262
6560
|
Number(tickLimitHigh),
|
|
@@ -6268,7 +6566,7 @@ async function simulateSwapExactIn(params) {
|
|
|
6268
6566
|
0
|
|
6269
6567
|
];
|
|
6270
6568
|
const tokenOutIndex = tokenInIndex === 0n ? 1n : 0n;
|
|
6271
|
-
const callData = buildSwapCallData(
|
|
6569
|
+
const callData = buildSwapCallData(creditTokenId, existingPositionIds, adjustedSize, mintTickLimits, burnTickLimits, builderCode);
|
|
6272
6570
|
const flowResult = await simulateWithTokenFlow({
|
|
6273
6571
|
client,
|
|
6274
6572
|
poolAddress,
|
|
@@ -7434,5 +7732,5 @@ function createEventPoller(params) {
|
|
|
7434
7732
|
}
|
|
7435
7733
|
|
|
7436
7734
|
//#endregion
|
|
7437
|
-
export { DEFAULT_RECONNECT_CONFIG, REQUIRED_BASE_ERROR_SENTINEL, addPendingPosition, addTrackedChunks, calculateAccountGreeksPure, calculateSpreadWad, checkCollateralAcrossTicks, cleanupStalePendingPositions, clearPendingPositions, clearTrackedChunks, clearTradeHistory, computeV4PoolId, confirmPendingPosition, convertToAssets, convertToShares, createEventPoller, createEventSubscription, createFlowNeutralTokenId, createPoolFormatters, decodePanopticTokenURI, encodePoolKeyBytes, encodeV3PoolKeyBytes, estimateBlockNumbers, estimateCollateralRequired, failPendingPosition, formatBlockNumber, formatBps, formatCompact, formatDatetime, formatDuration, formatDurationSeconds, formatFeeTier, formatGas, formatGwei, formatPoolIdHex, formatRatioPercent, formatTimestamp, formatTimestampLocale, formatTokenIdHex, formatTokenIdShort, formatTxHash, formatUtilization, formatWei, getAccountBuyingPower, getAccountGreeks, getAccountHistory, getAccountPremia, getChunkLiquidities, getChunkSpreads, getClosedPositions, getCollateralSharePrices, getCollateralTotalAssetsBatch, getDeltaHedgeParams, getEnforcedTickLimits, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getGuardianUnlockState, getItmAmounts, getMarginBuffer, getMaxPositionSize, getMaxWithdrawable, getNativeTokenPrice, getOpenPositionPreview, getPanopticPoolAddress, getPanopticPoolFromPoolId, getPendingPositions, getPoolDeploymentBlock, getPoolDisplayId, getPoolLiquidities, getPortfolioValue, getPositionChunkData, getPositionEnrichmentData, getPositionsWithPremia, getPriceHistory, getRealizedPnL, getRequiredCreditForITM, getSafeMode, getStreamiaHistory, getSyncStatus, getTokenListId, getTrackedChunks, getTradeHistory, getUniswapFeeHistory, getUniswapV3PoolFromId, getUniswapV3PoolInfo, getUniswapV3PoolLiquidities, getUniswapV4PoolBasicState, getUniswapV4PoolInfo, getUniswapV4PoolKeyFromId, getUniswapV4PoolLiquidities, interpolateBlocks, minePoolAddress, minePoolAddressLocalAsync, multicallRead, optimizeTokenIdRiskPartners, parseBps, parseCollateralLog, parsePoolLog, parseTokenListId, previewDeposit, previewMint, previewRedeem, previewWithdraw, reconstructFromEvents, removeTrackedChunks, resolveBlockNumbers, resolvePanopticPoolFromPoolId, resolveUniswapV4PoolKey, saveClosedPosition, scanChunks, simulateBatchDispatch, simulateClosePosition, simulateDeployNewPool, simulateDeposit, simulateDispatch, simulateForceExercise, simulateLiquidate, simulateSFPMBurn, simulateSFPMMint, simulateSettle, simulateSwapExactIn, simulateSwapExactOut, simulateWithdraw, truncateAddress, watchEvents };
|
|
7438
|
-
//# sourceMappingURL=v2-
|
|
7735
|
+
export { DEFAULT_RECONNECT_CONFIG, REQUIRED_BASE_ERROR_SENTINEL, addPendingPosition, addTrackedChunks, buildTokenShortfallRecoveryDispatch, calculateAccountGreeksPure, calculateSpreadWad, checkCollateralAcrossTicks, cleanupStalePendingPositions, clearPendingPositions, clearTrackedChunks, clearTradeHistory, computeV4PoolId, confirmPendingPosition, convertToAssets, convertToShares, createEventPoller, createEventSubscription, createFlowNeutralTokenId, createPoolFormatters, decodePanopticTokenURI, encodePoolKeyBytes, encodeV3PoolKeyBytes, estimateBlockNumbers, estimateCollateralRequired, failPendingPosition, formatBlockNumber, formatBps, formatCompact, formatDatetime, formatDuration, formatDurationSeconds, formatFeeTier, formatGas, formatGwei, formatPoolIdHex, formatRatioPercent, formatTimestamp, formatTimestampLocale, formatTokenIdHex, formatTokenIdShort, formatTxHash, formatUtilization, formatWei, getAccountBuyingPower, getAccountGreeks, getAccountHistory, getAccountPremia, getChunkLiquidities, getChunkSpreads, getClosedPositions, getCollateralSharePrices, getCollateralTotalAssetsBatch, getDeltaHedgeParams, getEnforcedTickLimits, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getGuardianUnlockState, getItmAmounts, getMarginBuffer, getMaxPositionSize, getMaxRedeem, getMaxWithdrawable, getNativeTokenPrice, getNotEnoughTokensError, getOpenPositionPreview, getPanopticPoolAddress, getPanopticPoolFromPoolId, getPendingPositions, getPoolDeploymentBlock, getPoolDisplayId, getPoolLiquidities, getPortfolioValue, getPositionChunkData, getPositionEnrichmentData, getPositionsWithPremia, getPriceHistory, getRealizedPnL, getRequiredCreditForITM, getSafeMode, getStreamiaHistory, getSyncStatus, getTokenListId, getTrackedChunks, getTradeHistory, getUniswapFeeHistory, getUniswapV3PoolFromId, getUniswapV3PoolInfo, getUniswapV3PoolLiquidities, getUniswapV4PoolBasicState, getUniswapV4PoolInfo, getUniswapV4PoolKeyFromId, getUniswapV4PoolLiquidities, interpolateBlocks, minePoolAddress, minePoolAddressLocalAsync, multicallRead, optimizeTokenIdRiskPartners, parseBps, parseCollateralLog, parsePoolLog, parseTokenListId, previewDeposit, previewMint, previewRedeem, previewWithdraw, quoteTokenShortfallRecovery, reconstructFromEvents, removeTrackedChunks, resolveBlockNumbers, resolvePanopticPoolFromPoolId, resolveUniswapV4PoolKey, saveClosedPosition, scanChunks, simulateBatchDispatch, simulateClosePosition, simulateDeployNewPool, simulateDeposit, simulateDispatch, simulateForceExercise, simulateLiquidate, simulateSFPMBurn, simulateSFPMMint, simulateSettle, simulateSwapExactIn, simulateSwapExactOut, simulateWithdraw, truncateAddress, watchEvents };
|
|
7736
|
+
//# sourceMappingURL=v2-DHJxPCAp.js.map
|