@panoptic-eng/sdk 1.0.47 → 1.0.48
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 +48 -4
- package/dist/cow/index.js.map +1 -1
- package/dist/{cow-DIYBU1j9.js → cow-BPcuMjYR.js} +1 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +203 -162
- package/dist/index.js.map +1 -1
- package/dist/{irm-CvLqxTAo.js → irm-C7QhFiwL.js} +7 -246
- package/dist/panoptic/v2/index.d.ts +167 -32
- package/dist/panoptic/v2/index.d.ts.map +1 -1
- package/dist/panoptic/v2/index.js +1562 -930
- package/dist/panoptic/v2/index.js.map +1 -1
- package/dist/panoptic/v2/react-public.d.ts +167 -32
- package/dist/panoptic/v2/react-public.d.ts.map +1 -1
- package/dist/panoptic/v2/react-public.js +1164 -528
- package/dist/panoptic/v2/react-public.js.map +1 -1
- package/dist/{getTrackedPositionIds-CwBHzOO2.js → rates-5oQD-SuM.js} +256 -4
- package/dist/{router-OcmdMkXx.js → router-C26q7i8w.js} +2 -2
- package/dist/{router-CUlQfzoc.js → router-ClhAkKjh.js} +1 -1
- package/dist/uniswap/index.js +59 -15
- package/dist/uniswap/index.js.map +1 -1
- package/dist/{v2-DeGgMN2a.js → v2-DVcophLf.js} +1379 -2671
- package/dist/{writes-BZW7UA4N.js → writes-DBHwfbDD.js} +2855 -944
- package/dist/zodiac/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -435,6 +435,19 @@ var SwapTokenMismatchError = class extends PanopticError {
|
|
|
435
435
|
this.token1 = token1;
|
|
436
436
|
}
|
|
437
437
|
};
|
|
438
|
+
/**
|
|
439
|
+
* A premium settlement would advance the seller checkpoint while some
|
|
440
|
+
* displayed premium is still unavailable, or a required buyer cannot settle.
|
|
441
|
+
*/
|
|
442
|
+
var UnsafePremiumSettlementError = class extends PanopticError {
|
|
443
|
+
name = "UnsafePremiumSettlementError";
|
|
444
|
+
constructor(remainingForfeit, failedBuyerCount, cause) {
|
|
445
|
+
const [token0, token1] = remainingForfeit;
|
|
446
|
+
super(failedBuyerCount > 0 ? `Premium settlement blocked: ${failedBuyerCount} buyer settlement${failedBuyerCount === 1 ? "" : "s"} would fail` : `Premium settlement blocked: uncollectable premium remains (${token0}, ${token1})`, cause);
|
|
447
|
+
this.remainingForfeit = remainingForfeit;
|
|
448
|
+
this.failedBuyerCount = failedBuyerCount;
|
|
449
|
+
}
|
|
450
|
+
};
|
|
438
451
|
|
|
439
452
|
//#endregion
|
|
440
453
|
//#region src/panoptic/v2/utils/interpolateBlocks.ts
|
|
@@ -10037,7 +10050,7 @@ function hasLoanOrCredit(tokenId) {
|
|
|
10037
10050
|
//#region src/panoptic/v2/formatters/tick.ts
|
|
10038
10051
|
const Q192$5 = 1n << 192n;
|
|
10039
10052
|
const RAW_PRICE_PRECISION = 40n;
|
|
10040
|
-
function pow10$
|
|
10053
|
+
function pow10$2(exponent) {
|
|
10041
10054
|
if (exponent < 0n) throw new RangeError("Exponent must be non-negative");
|
|
10042
10055
|
return 10n ** exponent;
|
|
10043
10056
|
}
|
|
@@ -10056,7 +10069,7 @@ function formatRatio$3(numerator, denominator, precision) {
|
|
|
10056
10069
|
if (precision < 0n) throw new RangeError("Precision must be non-negative");
|
|
10057
10070
|
const sign = numerator < 0n ? "-" : "";
|
|
10058
10071
|
const absNumerator = numerator < 0n ? -numerator : numerator;
|
|
10059
|
-
const scale = pow10$
|
|
10072
|
+
const scale = pow10$2(precision);
|
|
10060
10073
|
const scaled = (absNumerator * scale + denominator / 2n) / denominator;
|
|
10061
10074
|
const integerPart = scaled / scale;
|
|
10062
10075
|
const fractionalPart = scaled % scale;
|
|
@@ -10074,11 +10087,11 @@ function parseDecimalToFraction(value) {
|
|
|
10074
10087
|
const integerDigits = integerStr === "" ? "0" : integerStr;
|
|
10075
10088
|
const digits = `${integerDigits}${fractionalStr}`;
|
|
10076
10089
|
let numerator = BigInt(digits === "" ? "0" : digits);
|
|
10077
|
-
let denominator = pow10$
|
|
10090
|
+
let denominator = pow10$2(BigInt(fractionalStr.length));
|
|
10078
10091
|
if (exponentPart !== void 0 && exponentPart !== "") {
|
|
10079
10092
|
const exponent = BigInt(exponentPart);
|
|
10080
|
-
if (exponent > 0n) numerator *= pow10$
|
|
10081
|
-
else if (exponent < 0n) denominator *= pow10$
|
|
10093
|
+
if (exponent > 0n) numerator *= pow10$2(exponent);
|
|
10094
|
+
else if (exponent < 0n) denominator *= pow10$2(-exponent);
|
|
10082
10095
|
}
|
|
10083
10096
|
if (isNegative) numerator = -numerator;
|
|
10084
10097
|
return {
|
|
@@ -10138,12 +10151,12 @@ function adjustRatioForDecimals(numerator, denominator, decimals0, decimals1) {
|
|
|
10138
10151
|
denominator
|
|
10139
10152
|
};
|
|
10140
10153
|
if (diff > 0n) return {
|
|
10141
|
-
numerator: numerator * pow10$
|
|
10154
|
+
numerator: numerator * pow10$2(diff),
|
|
10142
10155
|
denominator
|
|
10143
10156
|
};
|
|
10144
10157
|
return {
|
|
10145
10158
|
numerator,
|
|
10146
|
-
denominator: denominator * pow10$
|
|
10159
|
+
denominator: denominator * pow10$2(-diff)
|
|
10147
10160
|
};
|
|
10148
10161
|
}
|
|
10149
10162
|
/**
|
|
@@ -10240,16 +10253,16 @@ function priceToTick(price, decimals0, decimals1) {
|
|
|
10240
10253
|
let targetNumerator = parsed.numerator;
|
|
10241
10254
|
let targetDenominator = parsed.denominator;
|
|
10242
10255
|
const diff = decimals0 - decimals1;
|
|
10243
|
-
if (diff > 0n) targetDenominator *= pow10$
|
|
10244
|
-
else if (diff < 0n) targetNumerator *= pow10$
|
|
10256
|
+
if (diff > 0n) targetDenominator *= pow10$2(diff);
|
|
10257
|
+
else if (diff < 0n) targetNumerator *= pow10$2(-diff);
|
|
10245
10258
|
let low = MIN_TICK;
|
|
10246
10259
|
let high = MAX_TICK;
|
|
10247
10260
|
while (low <= high) {
|
|
10248
10261
|
const mid = (low + high) / 2n;
|
|
10249
10262
|
const { numerator, denominator } = getRawPriceRatio(mid);
|
|
10250
|
-
const cmp = compareRatios(numerator, denominator, targetNumerator, targetDenominator);
|
|
10251
|
-
if (cmp === 0) return mid;
|
|
10252
|
-
if (cmp < 0) low = mid + 1n;
|
|
10263
|
+
const cmp$1 = compareRatios(numerator, denominator, targetNumerator, targetDenominator);
|
|
10264
|
+
if (cmp$1 === 0) return mid;
|
|
10265
|
+
if (cmp$1 < 0) low = mid + 1n;
|
|
10253
10266
|
else high = mid - 1n;
|
|
10254
10267
|
}
|
|
10255
10268
|
const floorTick = high;
|
|
@@ -10459,7 +10472,7 @@ function tickLimits(currentTick, toleranceBps) {
|
|
|
10459
10472
|
|
|
10460
10473
|
//#endregion
|
|
10461
10474
|
//#region src/panoptic/v2/tokenId/deriveUniqueTokenId.ts
|
|
10462
|
-
const POOL_ID_MASK$
|
|
10475
|
+
const POOL_ID_MASK$4 = (1n << 64n) - 1n;
|
|
10463
10476
|
const MAX_LEGS = TOKEN_ID_BITS.MAX_LEGS;
|
|
10464
10477
|
const MAX_OPTION_RATIO = LEG_LIMITS.MAX_RATIO;
|
|
10465
10478
|
const Q192$4 = 1n << 192n;
|
|
@@ -10566,7 +10579,7 @@ function scaleRatios(baseTokenId, targetPositionSize) {
|
|
|
10566
10579
|
const N = MAX_OPTION_RATIO / maxRatio;
|
|
10567
10580
|
if (N < 2n) throw new PanopticError("deriveUniqueTokenId: cannot derive a unique tokenId — all 4 leg slots used and optionRatios already near the 127 ceiling");
|
|
10568
10581
|
const newPositionSize = (targetPositionSize + N - 1n) / N;
|
|
10569
|
-
const poolId = baseTokenId & POOL_ID_MASK$
|
|
10582
|
+
const poolId = baseTokenId & POOL_ID_MASK$4;
|
|
10570
10583
|
let out = poolId;
|
|
10571
10584
|
for (const leg of legs) out = addLegToTokenId(out, {
|
|
10572
10585
|
index: leg.index,
|
|
@@ -11380,14 +11393,14 @@ function formatGwei(wei, precision) {
|
|
|
11380
11393
|
//#endregion
|
|
11381
11394
|
//#region src/panoptic/v2/tokenId/generateOverlapping.ts
|
|
11382
11395
|
const MAX_UINT64$2 = (1n << 64n) - 1n;
|
|
11383
|
-
const MAX_UINT128$
|
|
11396
|
+
const MAX_UINT128$4 = (1n << 128n) - 1n;
|
|
11384
11397
|
const Q192$3 = 1n << 192n;
|
|
11385
11398
|
const MAX_TOKEN_DECIMALS = 255n;
|
|
11386
11399
|
const MAX_DECIMAL_EXPONENT = 512n;
|
|
11387
11400
|
function invalid$1(message) {
|
|
11388
11401
|
throw new PanopticValidationError(`generateOverlappingTokenIds: ${message}`);
|
|
11389
11402
|
}
|
|
11390
|
-
function pow10(exponent) {
|
|
11403
|
+
function pow10$1(exponent) {
|
|
11391
11404
|
return 10n ** exponent;
|
|
11392
11405
|
}
|
|
11393
11406
|
function parsePriceSpacing(value, quoteDecimals) {
|
|
@@ -11400,7 +11413,7 @@ function parsePriceSpacing(value, quoteDecimals) {
|
|
|
11400
11413
|
let units = BigInt(`${integerPart}${fractionalPart}`);
|
|
11401
11414
|
let scale = BigInt(fractionalPart.length) - exponent;
|
|
11402
11415
|
if (scale < 0n) {
|
|
11403
|
-
units *= pow10(-scale);
|
|
11416
|
+
units *= pow10$1(-scale);
|
|
11404
11417
|
scale = 0n;
|
|
11405
11418
|
}
|
|
11406
11419
|
while (scale > 0n && units % 10n === 0n) {
|
|
@@ -11412,7 +11425,7 @@ function parsePriceSpacing(value, quoteDecimals) {
|
|
|
11412
11425
|
return {
|
|
11413
11426
|
units,
|
|
11414
11427
|
scale,
|
|
11415
|
-
denominator: pow10(scale)
|
|
11428
|
+
denominator: pow10$1(scale)
|
|
11416
11429
|
};
|
|
11417
11430
|
}
|
|
11418
11431
|
function formatGridPrice(multiple, spacing) {
|
|
@@ -11429,8 +11442,8 @@ function quotePriceAtTick(tick, asset, assetDecimals, quoteDecimals) {
|
|
|
11429
11442
|
let numerator = sqrtPriceX96 * sqrtPriceX96;
|
|
11430
11443
|
let denominator = Q192$3;
|
|
11431
11444
|
const decimalDifference = assetDecimals - quoteDecimals;
|
|
11432
|
-
if (decimalDifference > 0n) numerator *= pow10(decimalDifference);
|
|
11433
|
-
else if (decimalDifference < 0n) denominator *= pow10(-decimalDifference);
|
|
11445
|
+
if (decimalDifference > 0n) numerator *= pow10$1(decimalDifference);
|
|
11446
|
+
else if (decimalDifference < 0n) denominator *= pow10$1(-decimalDifference);
|
|
11434
11447
|
return {
|
|
11435
11448
|
numerator,
|
|
11436
11449
|
denominator
|
|
@@ -11447,12 +11460,12 @@ function isPriceGridStrike(strike, params, spacing, tickSpacing) {
|
|
|
11447
11460
|
}
|
|
11448
11461
|
return false;
|
|
11449
11462
|
}
|
|
11450
|
-
function ceilDiv$
|
|
11463
|
+
function ceilDiv$3(value, divisor) {
|
|
11451
11464
|
const quotient = value / divisor;
|
|
11452
11465
|
const remainder = value % divisor;
|
|
11453
11466
|
return remainder > 0n ? quotient + 1n : quotient;
|
|
11454
11467
|
}
|
|
11455
|
-
function floorDiv(value, divisor) {
|
|
11468
|
+
function floorDiv$1(value, divisor) {
|
|
11456
11469
|
const quotient = value / divisor;
|
|
11457
11470
|
const remainder = value % divisor;
|
|
11458
11471
|
return remainder < 0n ? quotient - 1n : quotient;
|
|
@@ -11480,8 +11493,8 @@ function resolveLegs(legs) {
|
|
|
11480
11493
|
function getCandidateStrikes(params, spacing, tickSpacing, halfWidth) {
|
|
11481
11494
|
const lower = MIN_TICK + halfWidth > params.currentTick - halfWidth + 1n ? MIN_TICK + halfWidth : params.currentTick - halfWidth + 1n;
|
|
11482
11495
|
const upper = MAX_TICK - halfWidth < params.currentTick + halfWidth - 1n ? MAX_TICK - halfWidth : params.currentTick + halfWidth - 1n;
|
|
11483
|
-
const firstStrike = ceilDiv$
|
|
11484
|
-
const lastStrike = floorDiv(upper, tickSpacing) * tickSpacing;
|
|
11496
|
+
const firstStrike = ceilDiv$3(lower, tickSpacing) * tickSpacing;
|
|
11497
|
+
const lastStrike = floorDiv$1(upper, tickSpacing) * tickSpacing;
|
|
11485
11498
|
const strikes = [];
|
|
11486
11499
|
for (let strike = firstStrike; strike <= lastStrike; strike += tickSpacing) if (isPriceGridStrike(strike, params, spacing, tickSpacing)) strikes.push(strike);
|
|
11487
11500
|
if (params.asset === 1n) strikes.reverse();
|
|
@@ -11521,7 +11534,7 @@ function generateOverlappingTokenIds(params) {
|
|
|
11521
11534
|
if (params.currentTick < MIN_TICK || params.currentTick > MAX_TICK) invalid$1(`currentTick must be between ${MIN_TICK} and ${MAX_TICK}`);
|
|
11522
11535
|
if (params.asset !== 0n && params.asset !== 1n) invalid$1("asset must be 0 or 1");
|
|
11523
11536
|
if (params.assetDecimals < 0n || params.assetDecimals > MAX_TOKEN_DECIMALS || params.quoteDecimals < 0n || params.quoteDecimals > MAX_TOKEN_DECIMALS) invalid$1("assetDecimals and quoteDecimals must be between 0 and 255");
|
|
11524
|
-
if (params.positionSize <= 0n || params.positionSize > MAX_UINT128$
|
|
11537
|
+
if (params.positionSize <= 0n || params.positionSize > MAX_UINT128$4) invalid$1("positionSize must be between 1 and uint128.max");
|
|
11525
11538
|
const tickSpacing = decodeTickSpacing(params.poolId);
|
|
11526
11539
|
if (tickSpacing <= 0n) invalid$1("poolId tick spacing must be positive");
|
|
11527
11540
|
const standardTickWidth = STANDARD_TICK_WIDTHS[params.timescale];
|
|
@@ -11542,15 +11555,15 @@ function generateOverlappingTokenIds(params) {
|
|
|
11542
11555
|
|
|
11543
11556
|
//#endregion
|
|
11544
11557
|
//#region src/panoptic/v2/tokenId/split.ts
|
|
11545
|
-
const POOL_ID_MASK$
|
|
11546
|
-
const MAX_UINT128$
|
|
11558
|
+
const POOL_ID_MASK$3 = (1n << TOKEN_ID_BITS.POOL_ID_SIZE) - 1n;
|
|
11559
|
+
const MAX_UINT128$3 = (1n << 128n) - 1n;
|
|
11547
11560
|
const MAX_UINT256$1 = (1n << 256n) - 1n;
|
|
11548
11561
|
function invalid(message) {
|
|
11549
11562
|
throw new PanopticValidationError(`splitTokenIdByTimescale: ${message}`);
|
|
11550
11563
|
}
|
|
11551
11564
|
function validateInput(tokenId, positionSize) {
|
|
11552
11565
|
if (tokenId < 0n || tokenId > MAX_UINT256$1) invalid("tokenId must fit in uint256");
|
|
11553
|
-
if (positionSize <= 0n || positionSize > MAX_UINT128$
|
|
11566
|
+
if (positionSize <= 0n || positionSize > MAX_UINT128$3) invalid("positionSize must be between 1 and uint128.max");
|
|
11554
11567
|
const legs = decodeAllLegs(tokenId);
|
|
11555
11568
|
if (legs.length === 0) invalid("tokenId must contain at least one active leg");
|
|
11556
11569
|
for (const [index, leg] of legs.entries()) if (leg.index !== BigInt(index)) invalid("active legs must be contiguous from index 0");
|
|
@@ -11679,7 +11692,7 @@ function splitTokenIdByTimescale(tokenId, positionSize, targetTimescale) {
|
|
|
11679
11692
|
const targetTickWidth = STANDARD_TICK_WIDTHS[targetTimescale];
|
|
11680
11693
|
if (targetTickWidth === void 0) invalid(`unknown target timescale ${String(targetTimescale)}`);
|
|
11681
11694
|
const targetWidth = (targetTickWidth + tickSpacing - 1n) / tickSpacing;
|
|
11682
|
-
const poolId = tokenId & POOL_ID_MASK$
|
|
11695
|
+
const poolId = tokenId & POOL_ID_MASK$3;
|
|
11683
11696
|
const optionLegs = legs.filter((leg) => leg.width > 0n);
|
|
11684
11697
|
const fundingLegs = legs.filter((leg) => leg.width === 0n);
|
|
11685
11698
|
const positionIdList = [];
|
|
@@ -13562,7 +13575,7 @@ async function fetchPoolId(params) {
|
|
|
13562
13575
|
//#endregion
|
|
13563
13576
|
//#region src/panoptic/v2/greeks/index.ts
|
|
13564
13577
|
/** Fixed-point scale constants for sqrtPriceX96 arithmetic */
|
|
13565
|
-
const Q96 = 1n << 96n;
|
|
13578
|
+
const Q96$1 = 1n << 96n;
|
|
13566
13579
|
const Q192$2 = 1n << 192n;
|
|
13567
13580
|
/**
|
|
13568
13581
|
* Convert tick to quote-denominated tick based on asset direction.
|
|
@@ -13710,7 +13723,7 @@ function computeOptionItm(m, qStrikeTick, qMintTick, halfWidthTick, isPut) {
|
|
|
13710
13723
|
const sqrtK = tickToSqrtPriceX96(qStrikeTick);
|
|
13711
13724
|
const sqrtPm = tickToSqrtPriceX96(qMintTick);
|
|
13712
13725
|
const rX192 = sqrtR * sqrtR;
|
|
13713
|
-
const sqrtKPmX96 = divTrunc(sqrtK * Q96, sqrtPm);
|
|
13726
|
+
const sqrtKPmX96 = divTrunc(sqrtK * Q96$1, sqrtPm);
|
|
13714
13727
|
const diff = sqrtR - sqrtKPmX96;
|
|
13715
13728
|
const diffSqX192 = diff * diff;
|
|
13716
13729
|
return divTrunc(m * diffSqX192, rX192 - Q192$2);
|
|
@@ -13782,7 +13795,7 @@ function getLegValue(leg, currentTick, mintTick, positionSize, poolTickSpacing,
|
|
|
13782
13795
|
const PX192 = sqrtP * sqrtP;
|
|
13783
13796
|
const KX192 = sqrtK * sqrtK;
|
|
13784
13797
|
const rX192 = sqrtR * sqrtR;
|
|
13785
|
-
const numerator = m * (2n * sqrtPKR * Q96 - PX192 - KX192);
|
|
13798
|
+
const numerator = m * (2n * sqrtPKR * Q96$1 - PX192 - KX192);
|
|
13786
13799
|
const denominator = rX192 - Q192$2;
|
|
13787
13800
|
v = divTrunc(numerator, denominator);
|
|
13788
13801
|
}
|
|
@@ -13890,7 +13903,7 @@ function getLegDelta(leg, currentTick, positionSize, poolTickSpacing, mintTick,
|
|
|
13890
13903
|
const sqrtK = tickToSqrtPriceX96(qStrikeTick);
|
|
13891
13904
|
const sqrtPm = tickToSqrtPriceX96(qMintTick);
|
|
13892
13905
|
const rX192 = sqrtR * sqrtR;
|
|
13893
|
-
const sqrtKPmX96 = sqrtK * Q96 / sqrtPm;
|
|
13906
|
+
const sqrtKPmX96 = sqrtK * Q96$1 / sqrtPm;
|
|
13894
13907
|
const diff = sqrtR - sqrtKPmX96;
|
|
13895
13908
|
const diffSqX192 = diff * diff;
|
|
13896
13909
|
return divTrunc(m * diffSqX192, rX192 - Q192$2);
|
|
@@ -13949,7 +13962,7 @@ function getLegGamma(leg, currentTick, positionSize, poolTickSpacing, assetIndex
|
|
|
13949
13962
|
const sqrtKPR = tickToSqrtPriceX96(qStrikeTick + qCurrentTick + halfWidthTick);
|
|
13950
13963
|
const sqrtR = tickToSqrtPriceX96(halfWidthTick);
|
|
13951
13964
|
const rX192 = sqrtR * sqrtR;
|
|
13952
|
-
const numerator = m * sqrtKPR * Q96;
|
|
13965
|
+
const numerator = m * sqrtKPR * Q96$1;
|
|
13953
13966
|
const denominator = 2n * (rX192 - Q192$2);
|
|
13954
13967
|
return divTrunc(numerator, denominator);
|
|
13955
13968
|
}
|
|
@@ -18070,7 +18083,7 @@ function maximumAmountIn(estimatedAmountIn, slippageBps) {
|
|
|
18070
18083
|
if (slippageBps < 0n) throw new PanopticError("slippageBps must be non-negative");
|
|
18071
18084
|
return (estimatedAmountIn * (BPS_DENOMINATOR$3 + slippageBps) + BPS_DENOMINATOR$3 - 1n) / BPS_DENOMINATOR$3;
|
|
18072
18085
|
}
|
|
18073
|
-
function ceilDiv(numerator, denominator) {
|
|
18086
|
+
function ceilDiv$2(numerator, denominator) {
|
|
18074
18087
|
return (numerator + denominator - 1n) / denominator;
|
|
18075
18088
|
}
|
|
18076
18089
|
function getInputAmount(tokenFlow, tokenInIndex) {
|
|
@@ -18185,7 +18198,7 @@ async function quoteTokenShortfallRecovery(params) {
|
|
|
18185
18198
|
error: new PanopticError("Insufficient source collateral for the recovery swap")
|
|
18186
18199
|
};
|
|
18187
18200
|
if (estimatedAmountOut < requiredOutput) {
|
|
18188
|
-
creditInput = estimatedAmountOut > 0n ? ceilDiv(creditInput * requiredOutput, estimatedAmountOut) + 1n : creditInput * 2n;
|
|
18201
|
+
creditInput = estimatedAmountOut > 0n ? ceilDiv$2(creditInput * requiredOutput, estimatedAmountOut) + 1n : creditInput * 2n;
|
|
18189
18202
|
continue;
|
|
18190
18203
|
}
|
|
18191
18204
|
const recoveredDispatch = buildPrefixedExactInputRecoveryDispatch({
|
|
@@ -18239,7 +18252,7 @@ async function quoteTokenShortfallRecovery(params) {
|
|
|
18239
18252
|
};
|
|
18240
18253
|
const residual = remainingShortfall.assetsRequested - remainingShortfall.assetBalance;
|
|
18241
18254
|
requiredOutput += residual > 0n ? residual : requiredOutput;
|
|
18242
|
-
creditInput = ceilDiv(creditInput * requiredOutput, estimatedAmountOut) + 1n;
|
|
18255
|
+
creditInput = ceilDiv$2(creditInput * requiredOutput, estimatedAmountOut) + 1n;
|
|
18243
18256
|
}
|
|
18244
18257
|
return {
|
|
18245
18258
|
available: false,
|
|
@@ -18295,7 +18308,7 @@ async function quoteTokenShortfallRecovery(params) {
|
|
|
18295
18308
|
const swapOutput = getOutputAmount(swapSimulation.tokenFlow, tokenOutIndex);
|
|
18296
18309
|
const sourceBalance = getBalanceBefore(swapSimulation.tokenFlow, tokenInIndex);
|
|
18297
18310
|
if (swapOutput < amountOut) {
|
|
18298
|
-
creditOutSize = swapOutput > 0n ? ceilDiv(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
|
|
18311
|
+
creditOutSize = swapOutput > 0n ? ceilDiv$2(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
|
|
18299
18312
|
continue;
|
|
18300
18313
|
}
|
|
18301
18314
|
if (sourceBalance < maxAmountIn) return {
|
|
@@ -18354,7 +18367,7 @@ async function quoteTokenShortfallRecovery(params) {
|
|
|
18354
18367
|
const decodedShortfall = remainingShortfall.assetsRequested - remainingShortfall.assetBalance;
|
|
18355
18368
|
const additionalAmountOut = decodedShortfall > 0n ? decodedShortfall : amountOut;
|
|
18356
18369
|
amountOut += additionalAmountOut;
|
|
18357
|
-
creditOutSize = swapOutput > 0n ? ceilDiv(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
|
|
18370
|
+
creditOutSize = swapOutput > 0n ? ceilDiv$2(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
|
|
18358
18371
|
}
|
|
18359
18372
|
return {
|
|
18360
18373
|
available: false,
|
|
@@ -18703,7 +18716,7 @@ async function getItmAmounts(params) {
|
|
|
18703
18716
|
*/
|
|
18704
18717
|
const FLOW_NEUTRAL_DUST_THRESHOLD = 1000n;
|
|
18705
18718
|
const Q192$1 = 1n << 192n;
|
|
18706
|
-
const POOL_ID_MASK$
|
|
18719
|
+
const POOL_ID_MASK$2 = (1n << 64n) - 1n;
|
|
18707
18720
|
/**
|
|
18708
18721
|
* Floor integer square root for bigints (Newton's method). Exact for all
|
|
18709
18722
|
* non-negative inputs — no float precision loss for values above 2^53.
|
|
@@ -18863,7 +18876,7 @@ async function createFlowNeutralTokenId(params) {
|
|
|
18863
18876
|
const measureSize = referenceSize !== void 0 && referenceSize > 0n && referenceSize < positionSize ? referenceSize : positionSize;
|
|
18864
18877
|
const legCount = countLegs(tokenId);
|
|
18865
18878
|
if (legCount >= 4n) throw new PanopticError("Cannot append neutralizing leg: tokenId already has 4 legs");
|
|
18866
|
-
const poolId = tokenId & POOL_ID_MASK$
|
|
18879
|
+
const poolId = tokenId & POOL_ID_MASK$2;
|
|
18867
18880
|
const baseLegs = decodeAllLegs(tokenId);
|
|
18868
18881
|
const prependNeutral = baseLegs.length === 1 && baseLegs[0].tokenType === baseLegs[0].asset;
|
|
18869
18882
|
let credit;
|
|
@@ -19170,7 +19183,7 @@ async function tryWithdrawSimulation(params) {
|
|
|
19170
19183
|
//#endregion
|
|
19171
19184
|
//#region src/panoptic/v2/reads/collateralBreakdown.ts
|
|
19172
19185
|
/** Mask selecting the poolId (low 64 bits) of a tokenId. */
|
|
19173
|
-
const POOL_ID_MASK = (1n << 64n) - 1n;
|
|
19186
|
+
const POOL_ID_MASK$1 = (1n << 64n) - 1n;
|
|
19174
19187
|
/** `getRequiredBase` prices at `type(uint64).max`; results scale linearly in size. */
|
|
19175
19188
|
const MAX_UINT64 = 2n ** 64n - 1n;
|
|
19176
19189
|
/** Kinds whose collateral rule is identical on-chain and must share one explanation. */
|
|
@@ -19295,7 +19308,7 @@ function isolateGroupTokenId(tokenId, legIndices) {
|
|
|
19295
19308
|
const byIndex = new Map(legs.map((leg) => [leg.index, leg]));
|
|
19296
19309
|
const ordered = [...legIndices].sort((x, y) => x < y ? -1 : x > y ? 1 : 0);
|
|
19297
19310
|
const remapped = new Map(ordered.map((old, i) => [old, BigInt(i)]));
|
|
19298
|
-
let out = tokenId & POOL_ID_MASK;
|
|
19311
|
+
let out = tokenId & POOL_ID_MASK$1;
|
|
19299
19312
|
for (const [index, oldIndex] of ordered.entries()) {
|
|
19300
19313
|
const leg = byIndex.get(oldIndex);
|
|
19301
19314
|
if (leg === void 0) throw new PanopticError(`isolateGroupTokenId: leg ${oldIndex} is not present in the tokenId`);
|
|
@@ -22166,7 +22179,7 @@ const nfpmAbi = [{
|
|
|
22166
22179
|
}],
|
|
22167
22180
|
stateMutability: "payable"
|
|
22168
22181
|
}];
|
|
22169
|
-
const MAX_UINT128$
|
|
22182
|
+
const MAX_UINT128$2 = 2n ** 128n - 1n;
|
|
22170
22183
|
const MAX_UINT256 = 2n ** 256n - 1n;
|
|
22171
22184
|
const Q128 = 2n ** 128n;
|
|
22172
22185
|
/**
|
|
@@ -22208,8 +22221,8 @@ async function getUniswapV3LpPositionState(params) {
|
|
|
22208
22221
|
args: [{
|
|
22209
22222
|
tokenId,
|
|
22210
22223
|
recipient: owner,
|
|
22211
|
-
amount0Max: MAX_UINT128$
|
|
22212
|
-
amount1Max: MAX_UINT128$
|
|
22224
|
+
amount0Max: MAX_UINT128$2,
|
|
22225
|
+
amount1Max: MAX_UINT128$2
|
|
22213
22226
|
}],
|
|
22214
22227
|
account: owner,
|
|
22215
22228
|
blockNumber: _meta.blockNumber
|
|
@@ -24586,214 +24599,864 @@ async function executeSettleSequenceAndWait(params) {
|
|
|
24586
24599
|
}
|
|
24587
24600
|
|
|
24588
24601
|
//#endregion
|
|
24589
|
-
//#region src/panoptic/v2/writes/
|
|
24590
|
-
|
|
24591
|
-
|
|
24592
|
-
|
|
24593
|
-
|
|
24594
|
-
|
|
24595
|
-
|
|
24596
|
-
|
|
24597
|
-
|
|
24598
|
-
|
|
24599
|
-
|
|
24600
|
-
|
|
24601
|
-
|
|
24602
|
-
|
|
24603
|
-
|
|
24604
|
-
|
|
24605
|
-
*
|
|
24606
|
-
|
|
24607
|
-
|
|
24608
|
-
|
|
24609
|
-
|
|
24610
|
-
|
|
24611
|
-
|
|
24612
|
-
|
|
24613
|
-
|
|
24614
|
-
|
|
24615
|
-
|
|
24616
|
-
|
|
24617
|
-
|
|
24618
|
-
|
|
24602
|
+
//#region src/panoptic/v2/writes/protectedSettle.ts
|
|
24603
|
+
const POOL_ID_MASK = (1n << 64n) - 1n;
|
|
24604
|
+
const Q96 = 1n << 96n;
|
|
24605
|
+
const MAX_UINT128$1 = (1n << 128n) - 1n;
|
|
24606
|
+
const SETTLE_LIMITS = [
|
|
24607
|
+
-887272n,
|
|
24608
|
+
887272n,
|
|
24609
|
+
0n
|
|
24610
|
+
];
|
|
24611
|
+
function ceilDiv$1(numerator, denominator) {
|
|
24612
|
+
return (numerator + denominator - 1n) / denominator;
|
|
24613
|
+
}
|
|
24614
|
+
/** Smallest position size that creates non-zero liquidity on every poke leg. */
|
|
24615
|
+
function minimumPokeSize(legs, tickSpacing) {
|
|
24616
|
+
let requiredSize = 1n;
|
|
24617
|
+
for (const leg of legs) {
|
|
24618
|
+
const widthInTicks = leg.width * tickSpacing;
|
|
24619
|
+
const lowerTick = leg.strike - widthInTicks / 2n;
|
|
24620
|
+
const upperTick = leg.strike + (widthInTicks + 1n) / 2n;
|
|
24621
|
+
const sqrtLower = tickToSqrtPriceX96(lowerTick);
|
|
24622
|
+
const sqrtUpper = tickToSqrtPriceX96(upperTick);
|
|
24623
|
+
const delta = sqrtUpper - sqrtLower;
|
|
24624
|
+
const liquidityFactor = leg.asset === 0n ? sqrtLower * sqrtUpper / Q96 : Q96;
|
|
24625
|
+
if (liquidityFactor === 0n) return void 0;
|
|
24626
|
+
const requiredAmount = ceilDiv$1(delta, liquidityFactor);
|
|
24627
|
+
const legSize = ceilDiv$1(requiredAmount, leg.optionRatio);
|
|
24628
|
+
if (legSize > requiredSize) requiredSize = legSize;
|
|
24629
|
+
}
|
|
24630
|
+
if (requiredSize > MAX_UINT128$1) return void 0;
|
|
24631
|
+
return requiredSize;
|
|
24632
|
+
}
|
|
24633
|
+
function encodePokeToken(sourceTokenId, legs, firstRatio, assetMask) {
|
|
24634
|
+
let tokenId = sourceTokenId & POOL_ID_MASK;
|
|
24635
|
+
legs.forEach((leg, index) => {
|
|
24636
|
+
const encodedIndex = BigInt(index);
|
|
24637
|
+
tokenId = addLegToTokenId(tokenId, {
|
|
24638
|
+
index: encodedIndex,
|
|
24639
|
+
asset: assetMask >> encodedIndex & 1n,
|
|
24640
|
+
optionRatio: index === 0 ? firstRatio : leg.optionRatio,
|
|
24641
|
+
isLong: 0n,
|
|
24642
|
+
tokenType: leg.tokenType,
|
|
24643
|
+
riskPartner: encodedIndex,
|
|
24644
|
+
strike: leg.strike,
|
|
24645
|
+
width: leg.width
|
|
24646
|
+
});
|
|
24619
24647
|
});
|
|
24620
|
-
|
|
24621
|
-
|
|
24622
|
-
|
|
24623
|
-
|
|
24624
|
-
|
|
24625
|
-
|
|
24626
|
-
|
|
24627
|
-
|
|
24628
|
-
|
|
24629
|
-
|
|
24630
|
-
abi: panopticPoolV2Abi,
|
|
24631
|
-
functionName: "dispatch",
|
|
24632
|
-
args: [
|
|
24633
|
-
positionIdList,
|
|
24634
|
-
finalPositionIdList ?? positionIdList,
|
|
24635
|
-
positionSizes.map((s) => BigInt(s)),
|
|
24636
|
-
tickAndSpreadLimits.map((t) => [
|
|
24637
|
-
Number(t[0]),
|
|
24638
|
-
Number(t[1]),
|
|
24639
|
-
Number(t[2])
|
|
24640
|
-
]),
|
|
24641
|
-
usePremiaAsCollateral,
|
|
24642
|
-
builderCode
|
|
24643
|
-
],
|
|
24644
|
-
txOverrides
|
|
24648
|
+
return tokenId;
|
|
24649
|
+
}
|
|
24650
|
+
function buildUniquePoke(sourceTokenId, occupied) {
|
|
24651
|
+
const seenChunks = new Set();
|
|
24652
|
+
const shortChunkLegs = decodeAllLegs(sourceTokenId).filter((leg) => {
|
|
24653
|
+
if (leg.isLong || leg.width === 0n) return false;
|
|
24654
|
+
const chunkKey = `${leg.strike}:${leg.width}:${leg.tokenType}`;
|
|
24655
|
+
if (seenChunks.has(chunkKey)) return false;
|
|
24656
|
+
seenChunks.add(chunkKey);
|
|
24657
|
+
return true;
|
|
24645
24658
|
});
|
|
24646
|
-
|
|
24647
|
-
|
|
24648
|
-
|
|
24649
|
-
|
|
24650
|
-
|
|
24651
|
-
|
|
24652
|
-
|
|
24653
|
-
|
|
24654
|
-
|
|
24655
|
-
|
|
24656
|
-
|
|
24657
|
-
|
|
24658
|
-
|
|
24659
|
-
|
|
24660
|
-
* This function can be called to advance the oracle epoch.
|
|
24661
|
-
* Note: The oracle can only be poked once per epoch (64 seconds).
|
|
24662
|
-
*
|
|
24663
|
-
* @param params - Poke oracle parameters
|
|
24664
|
-
* @returns TxResult
|
|
24665
|
-
* @throws OracleRateLimitedError if checkRateLimit is true and oracle was recently poked
|
|
24666
|
-
*
|
|
24667
|
-
* @example
|
|
24668
|
-
* ```typescript
|
|
24669
|
-
* const result = await pokeOracle({
|
|
24670
|
-
* client,
|
|
24671
|
-
* walletClient,
|
|
24672
|
-
* account,
|
|
24673
|
-
* poolAddress,
|
|
24674
|
-
* })
|
|
24675
|
-
* const receipt = await result.wait()
|
|
24676
|
-
* ```
|
|
24677
|
-
*/
|
|
24678
|
-
async function pokeOracle(params) {
|
|
24679
|
-
const { client, walletClient, account, poolAddress, checkRateLimit = false, txOverrides } = params;
|
|
24680
|
-
if (checkRateLimit) {
|
|
24681
|
-
const [oracleData, block] = await Promise.all([client.readContract({
|
|
24682
|
-
address: poolAddress,
|
|
24683
|
-
abi: panopticPoolV2Abi,
|
|
24684
|
-
functionName: "getOracleTicks"
|
|
24685
|
-
}), client.getBlock()]);
|
|
24686
|
-
const oraclePack = oracleData[4];
|
|
24687
|
-
const { epoch } = decodeOracleTiming(oraclePack, block.timestamp);
|
|
24688
|
-
const currentEpoch = oracleEpochAt(block.timestamp);
|
|
24689
|
-
if (currentEpoch === epoch) {
|
|
24690
|
-
const lastUpdate = epoch << 6n;
|
|
24691
|
-
throw new OracleRateLimitedError(lastUpdate, block.timestamp);
|
|
24659
|
+
if (shortChunkLegs.length === 0) return void 0;
|
|
24660
|
+
const originalRatio = shortChunkLegs[0].optionRatio;
|
|
24661
|
+
for (let ratioOffset = 0n; ratioOffset < 127n; ratioOffset += 1n) {
|
|
24662
|
+
const firstRatio = (originalRatio - 1n + ratioOffset) % 127n + 1n;
|
|
24663
|
+
const assetVariants = 1n << BigInt(shortChunkLegs.length);
|
|
24664
|
+
for (let assetMask = 0n; assetMask < assetVariants; assetMask += 1n) {
|
|
24665
|
+
const tokenId = encodePokeToken(sourceTokenId, shortChunkLegs, firstRatio, assetMask);
|
|
24666
|
+
if (!occupied.has(tokenId)) {
|
|
24667
|
+
const size = minimumPokeSize(decodeAllLegs(tokenId), decodeTickSpacing(sourceTokenId));
|
|
24668
|
+
if (size !== void 0) return {
|
|
24669
|
+
tokenId,
|
|
24670
|
+
size
|
|
24671
|
+
};
|
|
24672
|
+
}
|
|
24692
24673
|
}
|
|
24693
24674
|
}
|
|
24694
|
-
|
|
24695
|
-
|
|
24696
|
-
|
|
24697
|
-
|
|
24698
|
-
|
|
24699
|
-
|
|
24700
|
-
|
|
24701
|
-
|
|
24702
|
-
|
|
24675
|
+
throw new PanopticError("Unable to derive a collision-free protected settlement poke");
|
|
24676
|
+
}
|
|
24677
|
+
/**
|
|
24678
|
+
* Build `[poke, settle, poke]` for every target containing a width>0 short.
|
|
24679
|
+
* Pure-long and width-zero positions are settled directly.
|
|
24680
|
+
*/
|
|
24681
|
+
function buildProtectedSettlePlan(params) {
|
|
24682
|
+
const { positionIdList, finalPositionIdList, positionSizes, usePremiaAsCollateral = false, builderCode = 0n } = params;
|
|
24683
|
+
if (positionIdList.length !== positionSizes.length) throw new PanopticError("Protected settlement: positionSizes length must match positionIdList");
|
|
24684
|
+
const occupied = new Set(finalPositionIdList);
|
|
24685
|
+
const actionIds = [];
|
|
24686
|
+
const actionSizes = [];
|
|
24687
|
+
const actionLimits = [];
|
|
24688
|
+
const collectionIds = [];
|
|
24689
|
+
const collectionSizes = [];
|
|
24690
|
+
const collectionLimits = [];
|
|
24691
|
+
const pokingTokenIds = [];
|
|
24692
|
+
positionIdList.forEach((tokenId, index) => {
|
|
24693
|
+
const poke = buildUniquePoke(tokenId, occupied);
|
|
24694
|
+
if (poke === void 0) {
|
|
24695
|
+
actionIds.push(tokenId);
|
|
24696
|
+
actionSizes.push(positionSizes[index]);
|
|
24697
|
+
actionLimits.push(SETTLE_LIMITS);
|
|
24698
|
+
return;
|
|
24699
|
+
}
|
|
24700
|
+
occupied.add(poke.tokenId);
|
|
24701
|
+
pokingTokenIds.push(poke.tokenId);
|
|
24702
|
+
actionIds.push(poke.tokenId, tokenId, poke.tokenId);
|
|
24703
|
+
actionSizes.push(poke.size, positionSizes[index], 0n);
|
|
24704
|
+
actionLimits.push(SETTLE_LIMITS, SETTLE_LIMITS, SETTLE_LIMITS);
|
|
24705
|
+
collectionIds.push(poke.tokenId, poke.tokenId);
|
|
24706
|
+
collectionSizes.push(poke.size, 0n);
|
|
24707
|
+
collectionLimits.push(SETTLE_LIMITS, SETTLE_LIMITS);
|
|
24703
24708
|
});
|
|
24709
|
+
const base = {
|
|
24710
|
+
finalPositionIdList: [...finalPositionIdList],
|
|
24711
|
+
usePremiaAsCollateral,
|
|
24712
|
+
builderCode
|
|
24713
|
+
};
|
|
24714
|
+
return {
|
|
24715
|
+
dispatch: {
|
|
24716
|
+
...base,
|
|
24717
|
+
positionIdList: actionIds,
|
|
24718
|
+
positionSizes: actionSizes,
|
|
24719
|
+
tickAndSpreadLimits: actionLimits
|
|
24720
|
+
},
|
|
24721
|
+
collectionDispatch: collectionIds.length === 0 ? void 0 : {
|
|
24722
|
+
...base,
|
|
24723
|
+
positionIdList: collectionIds,
|
|
24724
|
+
positionSizes: collectionSizes,
|
|
24725
|
+
tickAndSpreadLimits: collectionLimits
|
|
24726
|
+
},
|
|
24727
|
+
pokingTokenIds
|
|
24728
|
+
};
|
|
24704
24729
|
}
|
|
24705
24730
|
/**
|
|
24706
|
-
*
|
|
24731
|
+
* Build the atomic self-settlement dispatch that temporarily pokes each
|
|
24732
|
+
* affected short chunk before settling its source position.
|
|
24733
|
+
*
|
|
24734
|
+
* @param params - Positions, current sizes, and complete held-position list.
|
|
24735
|
+
* @returns A dispatch intent ready for simulation or submission.
|
|
24707
24736
|
*/
|
|
24708
|
-
|
|
24709
|
-
|
|
24710
|
-
return result.wait();
|
|
24737
|
+
function buildProtectedSettleDispatch(params) {
|
|
24738
|
+
return buildProtectedSettlePlan(params).dispatch;
|
|
24711
24739
|
}
|
|
24712
24740
|
|
|
24713
24741
|
//#endregion
|
|
24714
|
-
//#region src/panoptic/v2/
|
|
24742
|
+
//#region src/panoptic/v2/simulations/simulateSettlePremiumFrom.ts
|
|
24743
|
+
/** Soft-failure revert markers for settle premium (target-state issues, not caller errors). */
|
|
24744
|
+
const SOFT_FAILURES = [
|
|
24745
|
+
{
|
|
24746
|
+
marker: "AccountInsolvent",
|
|
24747
|
+
reason: "Target account is insolvent; premium cannot be settled"
|
|
24748
|
+
},
|
|
24749
|
+
{
|
|
24750
|
+
marker: "PositionNotOwned",
|
|
24751
|
+
reason: "Target account no longer owns the position"
|
|
24752
|
+
},
|
|
24753
|
+
{
|
|
24754
|
+
marker: "StaleOracle",
|
|
24755
|
+
reason: "Oracle price is stale; settlement temporarily unavailable"
|
|
24756
|
+
},
|
|
24757
|
+
{
|
|
24758
|
+
marker: "InputListFail",
|
|
24759
|
+
reason: "Position list is stale (target positions changed)"
|
|
24760
|
+
}
|
|
24761
|
+
];
|
|
24715
24762
|
/**
|
|
24716
|
-
*
|
|
24763
|
+
* Simulate settling another account's accumulated long premium via `dispatchFrom`
|
|
24764
|
+
* (equal-length `positionIdListTo`/`positionIdListToFinal` selects the settle mode).
|
|
24717
24765
|
*
|
|
24718
|
-
*
|
|
24719
|
-
*
|
|
24766
|
+
* The measured token flow is the CALLER's collateral delta — i.e. the premium
|
|
24767
|
+
* the caller receives from the settlement (for chunks they sold).
|
|
24768
|
+
*
|
|
24769
|
+
* @param params - Simulation parameters
|
|
24770
|
+
* @returns Simulation result with settled premium data or error
|
|
24720
24771
|
*/
|
|
24721
|
-
async function
|
|
24722
|
-
const { client,
|
|
24723
|
-
|
|
24724
|
-
|
|
24725
|
-
walletClient,
|
|
24726
|
-
account,
|
|
24727
|
-
address: factoryAddress,
|
|
24728
|
-
abi: panopticFactoryV3Abi,
|
|
24729
|
-
functionName: "deployNewPool",
|
|
24730
|
-
args: [
|
|
24731
|
-
params.token0,
|
|
24732
|
-
params.token1,
|
|
24733
|
-
params.fee,
|
|
24734
|
-
riskEngine,
|
|
24735
|
-
salt
|
|
24736
|
-
],
|
|
24737
|
-
txOverrides
|
|
24738
|
-
});
|
|
24739
|
-
return submitWrite({
|
|
24772
|
+
async function simulateSettlePremiumFrom(params) {
|
|
24773
|
+
const { client, poolAddress, account, user, positionIdListFrom, positionIdList, tokenId, blockNumber } = params;
|
|
24774
|
+
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
24775
|
+
const metaPromise = getBlockMeta({
|
|
24740
24776
|
client,
|
|
24741
|
-
|
|
24742
|
-
account,
|
|
24743
|
-
address: factoryAddress,
|
|
24744
|
-
abi: panopticFactoryV4Abi,
|
|
24745
|
-
functionName: "deployNewPool",
|
|
24746
|
-
args: [
|
|
24747
|
-
{
|
|
24748
|
-
currency0: params.poolKey.currency0,
|
|
24749
|
-
currency1: params.poolKey.currency1,
|
|
24750
|
-
fee: Number(params.poolKey.fee),
|
|
24751
|
-
tickSpacing: Number(params.poolKey.tickSpacing),
|
|
24752
|
-
hooks: params.poolKey.hooks
|
|
24753
|
-
},
|
|
24754
|
-
riskEngine,
|
|
24755
|
-
salt
|
|
24756
|
-
],
|
|
24757
|
-
txOverrides
|
|
24777
|
+
blockNumber: targetBlockNumber
|
|
24758
24778
|
});
|
|
24759
|
-
|
|
24760
|
-
|
|
24761
|
-
|
|
24762
|
-
|
|
24763
|
-
|
|
24764
|
-
|
|
24765
|
-
|
|
24766
|
-
|
|
24767
|
-
|
|
24768
|
-
|
|
24769
|
-
|
|
24770
|
-
|
|
24771
|
-
|
|
24772
|
-
|
|
24773
|
-
|
|
24774
|
-
|
|
24775
|
-
|
|
24776
|
-
|
|
24777
|
-
|
|
24778
|
-
|
|
24779
|
-
}
|
|
24780
|
-
|
|
24781
|
-
|
|
24782
|
-
|
|
24783
|
-
|
|
24784
|
-
|
|
24785
|
-
|
|
24786
|
-
|
|
24787
|
-
|
|
24788
|
-
|
|
24789
|
-
|
|
24790
|
-
|
|
24791
|
-
|
|
24792
|
-
|
|
24793
|
-
|
|
24794
|
-
|
|
24795
|
-
|
|
24796
|
-
|
|
24779
|
+
const emptyTokenFlow = {
|
|
24780
|
+
delta0: 0n,
|
|
24781
|
+
delta1: 0n,
|
|
24782
|
+
balanceBefore0: 0n,
|
|
24783
|
+
balanceBefore1: 0n,
|
|
24784
|
+
balanceAfter0: 0n,
|
|
24785
|
+
balanceAfter1: 0n,
|
|
24786
|
+
tickBefore: null,
|
|
24787
|
+
tickAfter: null
|
|
24788
|
+
};
|
|
24789
|
+
const softFailure = (errorMessage) => {
|
|
24790
|
+
const match = SOFT_FAILURES.find(({ marker }) => errorMessage.includes(marker));
|
|
24791
|
+
return match ? {
|
|
24792
|
+
premium0: 0n,
|
|
24793
|
+
premium1: 0n,
|
|
24794
|
+
settled0: 0n,
|
|
24795
|
+
settled1: 0n,
|
|
24796
|
+
canSettle: false,
|
|
24797
|
+
reason: match.reason
|
|
24798
|
+
} : null;
|
|
24799
|
+
};
|
|
24800
|
+
try {
|
|
24801
|
+
const orderedList = tokenId !== void 0 ? orderListForSettle(positionIdList, tokenId) : positionIdList;
|
|
24802
|
+
const callData = encodeFunctionData({
|
|
24803
|
+
abi: panopticPoolV2Abi,
|
|
24804
|
+
functionName: "dispatchFrom",
|
|
24805
|
+
args: [
|
|
24806
|
+
positionIdListFrom,
|
|
24807
|
+
user,
|
|
24808
|
+
orderedList,
|
|
24809
|
+
orderedList,
|
|
24810
|
+
0n
|
|
24811
|
+
]
|
|
24812
|
+
});
|
|
24813
|
+
const availablePremiumCallData = encodeFunctionData({
|
|
24814
|
+
abi: panopticPoolV2Abi,
|
|
24815
|
+
functionName: "getFullPositionsData",
|
|
24816
|
+
args: [
|
|
24817
|
+
account,
|
|
24818
|
+
false,
|
|
24819
|
+
positionIdListFrom
|
|
24820
|
+
]
|
|
24821
|
+
});
|
|
24822
|
+
const buyerOwedCallData = encodeFunctionData({
|
|
24823
|
+
abi: panopticPoolV2Abi,
|
|
24824
|
+
functionName: "getFullPositionsData",
|
|
24825
|
+
args: [
|
|
24826
|
+
user,
|
|
24827
|
+
true,
|
|
24828
|
+
orderedList
|
|
24829
|
+
]
|
|
24830
|
+
});
|
|
24831
|
+
const flowResult = await simulateWithTokenFlow({
|
|
24832
|
+
client,
|
|
24833
|
+
poolAddress,
|
|
24834
|
+
user: account,
|
|
24835
|
+
callData,
|
|
24836
|
+
blockNumber: targetBlockNumber,
|
|
24837
|
+
preCallData: [availablePremiumCallData, buyerOwedCallData],
|
|
24838
|
+
postCallData: [availablePremiumCallData, buyerOwedCallData]
|
|
24839
|
+
});
|
|
24840
|
+
if (!flowResult.success || !flowResult.tokenFlow) {
|
|
24841
|
+
const errorMessage = flowResult.error || "Simulation failed";
|
|
24842
|
+
const soft = softFailure(errorMessage);
|
|
24843
|
+
if (soft) {
|
|
24844
|
+
const _meta$1 = await metaPromise;
|
|
24845
|
+
return {
|
|
24846
|
+
success: true,
|
|
24847
|
+
data: soft,
|
|
24848
|
+
gasEstimate: 0n,
|
|
24849
|
+
tokenFlow: emptyTokenFlow,
|
|
24850
|
+
_meta: _meta$1
|
|
24851
|
+
};
|
|
24852
|
+
}
|
|
24853
|
+
throw new PanopticError(errorMessage);
|
|
24854
|
+
}
|
|
24855
|
+
const _meta = await metaPromise;
|
|
24856
|
+
const tokenFlow = flowResult.tokenFlow;
|
|
24857
|
+
const decodePremia = (raw) => {
|
|
24858
|
+
const [shortPremiumPacked, longPremiumPacked] = decodeFunctionResult({
|
|
24859
|
+
abi: panopticPoolV2Abi,
|
|
24860
|
+
functionName: "getFullPositionsData",
|
|
24861
|
+
data: raw
|
|
24862
|
+
});
|
|
24863
|
+
const short = decodeLeftRightUnsigned(shortPremiumPacked);
|
|
24864
|
+
const long = decodeLeftRightUnsigned(longPremiumPacked);
|
|
24865
|
+
return {
|
|
24866
|
+
short0: short.right,
|
|
24867
|
+
short1: short.left,
|
|
24868
|
+
long0: long.right,
|
|
24869
|
+
long1: long.left
|
|
24870
|
+
};
|
|
24871
|
+
};
|
|
24872
|
+
let premium0 = 0n;
|
|
24873
|
+
let premium1 = 0n;
|
|
24874
|
+
const preRaw = flowResult.preCallResults?.[0];
|
|
24875
|
+
const postRaw = flowResult.postCallResults?.[0];
|
|
24876
|
+
if (preRaw !== void 0 && postRaw !== void 0) {
|
|
24877
|
+
const pre = decodePremia(preRaw);
|
|
24878
|
+
const post = decodePremia(postRaw);
|
|
24879
|
+
premium0 = post.short0 > pre.short0 ? post.short0 - pre.short0 : 0n;
|
|
24880
|
+
premium1 = post.short1 > pre.short1 ? post.short1 - pre.short1 : 0n;
|
|
24881
|
+
}
|
|
24882
|
+
let settled0 = 0n;
|
|
24883
|
+
let settled1 = 0n;
|
|
24884
|
+
const preBuyerRaw = flowResult.preCallResults?.[1];
|
|
24885
|
+
const postBuyerRaw = flowResult.postCallResults?.[1];
|
|
24886
|
+
if (preBuyerRaw !== void 0 && postBuyerRaw !== void 0) {
|
|
24887
|
+
const pre = decodePremia(preBuyerRaw);
|
|
24888
|
+
const post = decodePremia(postBuyerRaw);
|
|
24889
|
+
settled0 = pre.long0 > post.long0 ? pre.long0 - post.long0 : 0n;
|
|
24890
|
+
settled1 = pre.long1 > post.long1 ? pre.long1 - post.long1 : 0n;
|
|
24891
|
+
}
|
|
24892
|
+
const data = {
|
|
24893
|
+
premium0,
|
|
24894
|
+
premium1,
|
|
24895
|
+
settled0,
|
|
24896
|
+
settled1,
|
|
24897
|
+
canSettle: true
|
|
24898
|
+
};
|
|
24899
|
+
return {
|
|
24900
|
+
success: true,
|
|
24901
|
+
data,
|
|
24902
|
+
gasEstimate: flowResult.gasEstimate,
|
|
24903
|
+
tokenFlow,
|
|
24904
|
+
_meta
|
|
24905
|
+
};
|
|
24906
|
+
} catch (error) {
|
|
24907
|
+
const _meta = await metaPromise;
|
|
24908
|
+
const errorMessage = error instanceof Error ? error.message : "Simulation failed";
|
|
24909
|
+
const soft = softFailure(errorMessage);
|
|
24910
|
+
if (soft) return {
|
|
24911
|
+
success: true,
|
|
24912
|
+
data: soft,
|
|
24913
|
+
gasEstimate: 0n,
|
|
24914
|
+
tokenFlow: emptyTokenFlow,
|
|
24915
|
+
_meta
|
|
24916
|
+
};
|
|
24917
|
+
return {
|
|
24918
|
+
success: false,
|
|
24919
|
+
error: error instanceof PanopticError ? error : new PanopticError(errorMessage, error instanceof Error ? error : void 0),
|
|
24920
|
+
_meta
|
|
24921
|
+
};
|
|
24922
|
+
}
|
|
24923
|
+
}
|
|
24924
|
+
|
|
24925
|
+
//#endregion
|
|
24926
|
+
//#region src/panoptic/v2/simulations/simulateSettlePremiumBatch.ts
|
|
24927
|
+
/**
|
|
24928
|
+
* Simulate settling each target buyer's owed long premium, all at one block.
|
|
24929
|
+
*
|
|
24930
|
+
* Individual failures (insolvent buyer, stale list, …) are soft: the target
|
|
24931
|
+
* lands in the unsettleable partition instead of failing the batch. Only
|
|
24932
|
+
* unexpected errors reject.
|
|
24933
|
+
*
|
|
24934
|
+
* @param params - Simulation parameters
|
|
24935
|
+
* @returns Partitioned targets with per-target premium and totals
|
|
24936
|
+
*/
|
|
24937
|
+
async function simulateSettlePremiumBatch(params) {
|
|
24938
|
+
const { client, poolAddress, account, positionIdListFrom, targets, blockNumber } = params;
|
|
24939
|
+
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
24940
|
+
const metaPromise = getBlockMeta({
|
|
24941
|
+
client,
|
|
24942
|
+
blockNumber: targetBlockNumber
|
|
24943
|
+
});
|
|
24944
|
+
const simulations = await Promise.all(targets.map((target) => simulateSettlePremiumFrom({
|
|
24945
|
+
client,
|
|
24946
|
+
poolAddress,
|
|
24947
|
+
account,
|
|
24948
|
+
user: target.user,
|
|
24949
|
+
positionIdListFrom,
|
|
24950
|
+
positionIdList: target.positionIdList,
|
|
24951
|
+
tokenId: target.tokenId,
|
|
24952
|
+
blockNumber: targetBlockNumber
|
|
24953
|
+
})));
|
|
24954
|
+
const results = [];
|
|
24955
|
+
const settleable = [];
|
|
24956
|
+
let unsettleableCount = 0;
|
|
24957
|
+
let premium0 = 0n;
|
|
24958
|
+
let premium1 = 0n;
|
|
24959
|
+
simulations.forEach((sim, i) => {
|
|
24960
|
+
const simulation = sim.success ? sim.data : {
|
|
24961
|
+
premium0: 0n,
|
|
24962
|
+
premium1: 0n,
|
|
24963
|
+
settled0: 0n,
|
|
24964
|
+
settled1: 0n,
|
|
24965
|
+
canSettle: false,
|
|
24966
|
+
reason: sim.error.message
|
|
24967
|
+
};
|
|
24968
|
+
results.push({
|
|
24969
|
+
target: targets[i],
|
|
24970
|
+
simulation
|
|
24971
|
+
});
|
|
24972
|
+
if (simulation.canSettle) {
|
|
24973
|
+
settleable.push(targets[i]);
|
|
24974
|
+
premium0 += simulation.premium0;
|
|
24975
|
+
premium1 += simulation.premium1;
|
|
24976
|
+
} else unsettleableCount += 1;
|
|
24977
|
+
});
|
|
24978
|
+
const _meta = await metaPromise;
|
|
24979
|
+
return {
|
|
24980
|
+
results,
|
|
24981
|
+
settleable,
|
|
24982
|
+
unsettleableCount,
|
|
24983
|
+
premium0,
|
|
24984
|
+
premium1,
|
|
24985
|
+
_meta
|
|
24986
|
+
};
|
|
24987
|
+
}
|
|
24988
|
+
/**
|
|
24989
|
+
* Simulate a full settle sequence (all settles + optional close) as the one
|
|
24990
|
+
* multicall that `executeSettleSequence` submits, measuring the caller's
|
|
24991
|
+
* total token flow and gas.
|
|
24992
|
+
*
|
|
24993
|
+
* @param params - Simulation parameters
|
|
24994
|
+
* @returns Simulation result with the caller's net flow, or error
|
|
24995
|
+
*/
|
|
24996
|
+
async function simulateSettleSequence(params) {
|
|
24997
|
+
const { client, poolAddress, account, blockNumber } = params;
|
|
24998
|
+
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
24999
|
+
const metaPromise = getBlockMeta({
|
|
25000
|
+
client,
|
|
25001
|
+
blockNumber: targetBlockNumber
|
|
25002
|
+
});
|
|
25003
|
+
try {
|
|
25004
|
+
const calls = buildSettleSequenceCalls(params);
|
|
25005
|
+
const callData = encodeFunctionData({
|
|
25006
|
+
abi: panopticPoolV2Abi,
|
|
25007
|
+
functionName: "multicall",
|
|
25008
|
+
args: [calls]
|
|
25009
|
+
});
|
|
25010
|
+
const flowResult = await simulateWithTokenFlow({
|
|
25011
|
+
client,
|
|
25012
|
+
poolAddress,
|
|
25013
|
+
user: account,
|
|
25014
|
+
callData,
|
|
25015
|
+
blockNumber: targetBlockNumber
|
|
25016
|
+
});
|
|
25017
|
+
if (!flowResult.success || !flowResult.tokenFlow) throw new PanopticError(flowResult.error || "Simulation failed");
|
|
25018
|
+
const _meta = await metaPromise;
|
|
25019
|
+
const tokenFlow = flowResult.tokenFlow;
|
|
25020
|
+
return {
|
|
25021
|
+
success: true,
|
|
25022
|
+
data: {
|
|
25023
|
+
delta0: tokenFlow.delta0,
|
|
25024
|
+
delta1: tokenFlow.delta1
|
|
25025
|
+
},
|
|
25026
|
+
gasEstimate: flowResult.gasEstimate,
|
|
25027
|
+
tokenFlow,
|
|
25028
|
+
_meta
|
|
25029
|
+
};
|
|
25030
|
+
} catch (error) {
|
|
25031
|
+
const _meta = await metaPromise;
|
|
25032
|
+
const errorMessage = error instanceof Error ? error.message : "Simulation failed";
|
|
25033
|
+
return {
|
|
25034
|
+
success: false,
|
|
25035
|
+
error: error instanceof PanopticError ? error : new PanopticError(errorMessage, error instanceof Error ? error : void 0),
|
|
25036
|
+
_meta
|
|
25037
|
+
};
|
|
25038
|
+
}
|
|
25039
|
+
}
|
|
25040
|
+
|
|
25041
|
+
//#endregion
|
|
25042
|
+
//#region src/panoptic/v2/simulations/simulateSettle.ts
|
|
25043
|
+
const BIT_MASK_128 = (1n << 128n) - 1n;
|
|
25044
|
+
const multicallAbi = [{
|
|
25045
|
+
type: "function",
|
|
25046
|
+
name: "multicall",
|
|
25047
|
+
inputs: [{
|
|
25048
|
+
name: "data",
|
|
25049
|
+
type: "bytes[]"
|
|
25050
|
+
}],
|
|
25051
|
+
outputs: [{
|
|
25052
|
+
name: "results",
|
|
25053
|
+
type: "bytes[]"
|
|
25054
|
+
}],
|
|
25055
|
+
stateMutability: "nonpayable"
|
|
25056
|
+
}];
|
|
25057
|
+
function encodeDispatch(plan) {
|
|
25058
|
+
const dispatch$1 = plan.dispatch;
|
|
25059
|
+
return encodeFunctionData({
|
|
25060
|
+
abi: panopticPoolV2Abi,
|
|
25061
|
+
functionName: "dispatch",
|
|
25062
|
+
args: [
|
|
25063
|
+
dispatch$1.positionIdList,
|
|
25064
|
+
dispatch$1.finalPositionIdList,
|
|
25065
|
+
dispatch$1.positionSizes,
|
|
25066
|
+
dispatch$1.tickAndSpreadLimits.map((limits) => [
|
|
25067
|
+
Number(limits[0]),
|
|
25068
|
+
Number(limits[1]),
|
|
25069
|
+
Number(limits[2])
|
|
25070
|
+
]),
|
|
25071
|
+
dispatch$1.usePremiaAsCollateral,
|
|
25072
|
+
dispatch$1.builderCode
|
|
25073
|
+
]
|
|
25074
|
+
});
|
|
25075
|
+
}
|
|
25076
|
+
function decodeShortPremium(data) {
|
|
25077
|
+
const packed = decodeFunctionResult({
|
|
25078
|
+
abi: panopticPoolV2Abi,
|
|
25079
|
+
functionName: "getFullPositionsData",
|
|
25080
|
+
data
|
|
25081
|
+
})[0];
|
|
25082
|
+
return [packed & BIT_MASK_128, packed >> 128n];
|
|
25083
|
+
}
|
|
25084
|
+
async function remainingForfeitAfterProtection(params) {
|
|
25085
|
+
const { client, poolAddress, account, positionIdList, targets, plan, blockNumber, initial } = params;
|
|
25086
|
+
if (targets.length === 0 && plan.collectionDispatch === void 0) return [...initial];
|
|
25087
|
+
const protectionCalls = buildSettleSequenceCalls({
|
|
25088
|
+
positionIdListFrom: params.finalPositionIdList,
|
|
25089
|
+
targets,
|
|
25090
|
+
dispatch: plan.collectionDispatch
|
|
25091
|
+
});
|
|
25092
|
+
const availableCall = encodeFunctionData({
|
|
25093
|
+
abi: panopticPoolV2Abi,
|
|
25094
|
+
functionName: "getFullPositionsData",
|
|
25095
|
+
args: [
|
|
25096
|
+
account,
|
|
25097
|
+
false,
|
|
25098
|
+
positionIdList
|
|
25099
|
+
]
|
|
25100
|
+
});
|
|
25101
|
+
const totalCall = encodeFunctionData({
|
|
25102
|
+
abi: panopticPoolV2Abi,
|
|
25103
|
+
functionName: "getFullPositionsData",
|
|
25104
|
+
args: [
|
|
25105
|
+
account,
|
|
25106
|
+
true,
|
|
25107
|
+
positionIdList
|
|
25108
|
+
]
|
|
25109
|
+
});
|
|
25110
|
+
const { result } = await client.simulateContract({
|
|
25111
|
+
address: poolAddress,
|
|
25112
|
+
abi: multicallAbi,
|
|
25113
|
+
functionName: "multicall",
|
|
25114
|
+
args: [[
|
|
25115
|
+
...protectionCalls,
|
|
25116
|
+
availableCall,
|
|
25117
|
+
totalCall
|
|
25118
|
+
]],
|
|
25119
|
+
account,
|
|
25120
|
+
blockNumber
|
|
25121
|
+
});
|
|
25122
|
+
const available = decodeShortPremium(result[result.length - 2]);
|
|
25123
|
+
const total = decodeShortPremium(result[result.length - 1]);
|
|
25124
|
+
return [total[0] > available[0] ? total[0] - available[0] : 0n, total[1] > available[1] ? total[1] - available[1] : 0n];
|
|
25125
|
+
}
|
|
25126
|
+
async function simulateSettle(params) {
|
|
25127
|
+
const { client, poolAddress, account, positionIdList, finalPositionIdList = positionIdList, positionSizes: providedSizes, targets = [], usePremiaAsCollateral = false, builderCode = 0n, allowForfeit = false, blockNumber } = params;
|
|
25128
|
+
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
25129
|
+
const metaPromise = getBlockMeta({
|
|
25130
|
+
client,
|
|
25131
|
+
blockNumber: targetBlockNumber
|
|
25132
|
+
});
|
|
25133
|
+
try {
|
|
25134
|
+
if (providedSizes && providedSizes.length !== positionIdList.length) throw new PanopticError("simulateSettle: positionSizes length must match positionIdList");
|
|
25135
|
+
const positionSizes = providedSizes ?? await getCurrentPositionSizes({
|
|
25136
|
+
client,
|
|
25137
|
+
poolAddress,
|
|
25138
|
+
account,
|
|
25139
|
+
positionIdList,
|
|
25140
|
+
blockNumber: targetBlockNumber
|
|
25141
|
+
});
|
|
25142
|
+
const plan = buildProtectedSettlePlan({
|
|
25143
|
+
positionIdList,
|
|
25144
|
+
finalPositionIdList,
|
|
25145
|
+
positionSizes,
|
|
25146
|
+
usePremiaAsCollateral,
|
|
25147
|
+
builderCode
|
|
25148
|
+
});
|
|
25149
|
+
const initialForfeit = await getForfeitablePremium({
|
|
25150
|
+
client,
|
|
25151
|
+
poolAddress,
|
|
25152
|
+
account,
|
|
25153
|
+
tokenIds: positionIdList,
|
|
25154
|
+
blockNumber: targetBlockNumber
|
|
25155
|
+
});
|
|
25156
|
+
const initial = [initialForfeit.forfeit0, initialForfeit.forfeit1];
|
|
25157
|
+
if (targets.length > 0) {
|
|
25158
|
+
const buyers = await simulateSettlePremiumBatch({
|
|
25159
|
+
client,
|
|
25160
|
+
poolAddress,
|
|
25161
|
+
account,
|
|
25162
|
+
positionIdListFrom: finalPositionIdList,
|
|
25163
|
+
targets,
|
|
25164
|
+
blockNumber: targetBlockNumber
|
|
25165
|
+
});
|
|
25166
|
+
if (buyers.unsettleableCount > 0) throw new UnsafePremiumSettlementError(initial, buyers.unsettleableCount);
|
|
25167
|
+
}
|
|
25168
|
+
const remainingForfeit = await remainingForfeitAfterProtection({
|
|
25169
|
+
client,
|
|
25170
|
+
poolAddress,
|
|
25171
|
+
account,
|
|
25172
|
+
positionIdList,
|
|
25173
|
+
finalPositionIdList,
|
|
25174
|
+
targets,
|
|
25175
|
+
plan,
|
|
25176
|
+
blockNumber: targetBlockNumber,
|
|
25177
|
+
initial
|
|
25178
|
+
});
|
|
25179
|
+
if ((remainingForfeit[0] > 0n || remainingForfeit[1] > 0n) && !allowForfeit) throw new UnsafePremiumSettlementError(remainingForfeit, 0);
|
|
25180
|
+
const callData = targets.length === 0 ? encodeDispatch(plan) : encodeFunctionData({
|
|
25181
|
+
abi: panopticPoolV2Abi,
|
|
25182
|
+
functionName: "multicall",
|
|
25183
|
+
args: [buildSettleSequenceCalls({
|
|
25184
|
+
positionIdListFrom: finalPositionIdList,
|
|
25185
|
+
targets,
|
|
25186
|
+
dispatch: plan.dispatch
|
|
25187
|
+
})]
|
|
25188
|
+
});
|
|
25189
|
+
const flowResult = await simulateWithTokenFlow({
|
|
25190
|
+
client,
|
|
25191
|
+
poolAddress,
|
|
25192
|
+
user: account,
|
|
25193
|
+
callData,
|
|
25194
|
+
blockNumber: targetBlockNumber
|
|
25195
|
+
});
|
|
25196
|
+
if (!flowResult.success || !flowResult.tokenFlow) throw flowResult.rawError ?? new PanopticError(flowResult.error || "Simulation failed");
|
|
25197
|
+
const tokenFlow = flowResult.tokenFlow;
|
|
25198
|
+
return {
|
|
25199
|
+
success: true,
|
|
25200
|
+
data: {
|
|
25201
|
+
premiaReceived0: tokenFlow.delta0,
|
|
25202
|
+
premiaReceived1: tokenFlow.delta1,
|
|
25203
|
+
postCollateral0: tokenFlow.balanceAfter0,
|
|
25204
|
+
postCollateral1: tokenFlow.balanceAfter1,
|
|
25205
|
+
premiumProtected: [initial[0] - remainingForfeit[0], initial[1] - remainingForfeit[1]],
|
|
25206
|
+
remainingForfeit,
|
|
25207
|
+
usesPoke: plan.pokingTokenIds.length > 0,
|
|
25208
|
+
settledBuyerCount: targets.length
|
|
25209
|
+
},
|
|
25210
|
+
gasEstimate: flowResult.gasEstimate,
|
|
25211
|
+
tokenFlow,
|
|
25212
|
+
_meta: await metaPromise
|
|
25213
|
+
};
|
|
25214
|
+
} catch (error) {
|
|
25215
|
+
return {
|
|
25216
|
+
success: false,
|
|
25217
|
+
error: error instanceof PanopticError ? error : new PanopticError(error instanceof Error ? error.message : "Simulation failed", error instanceof Error ? error : void 0),
|
|
25218
|
+
_meta: await metaPromise
|
|
25219
|
+
};
|
|
25220
|
+
}
|
|
25221
|
+
}
|
|
25222
|
+
|
|
25223
|
+
//#endregion
|
|
25224
|
+
//#region src/panoptic/v2/writes/settle.ts
|
|
25225
|
+
/**
|
|
25226
|
+
* Settle accumulated premia on existing positions.
|
|
25227
|
+
*
|
|
25228
|
+
* This function triggers premium collection without changing position size.
|
|
25229
|
+
* It calls dispatch with unchanged position lists.
|
|
25230
|
+
*
|
|
25231
|
+
* @param params - Settlement parameters
|
|
25232
|
+
* @returns TxResult
|
|
25233
|
+
*
|
|
25234
|
+
* @example
|
|
25235
|
+
* ```typescript
|
|
25236
|
+
* const result = await settleAccumulatedPremia({
|
|
25237
|
+
* client,
|
|
25238
|
+
* walletClient,
|
|
25239
|
+
* account,
|
|
25240
|
+
* poolAddress,
|
|
25241
|
+
* positionIdList: existingPositions,
|
|
25242
|
+
* })
|
|
25243
|
+
* const receipt = await result.wait()
|
|
25244
|
+
* ```
|
|
25245
|
+
*/
|
|
25246
|
+
async function settleAccumulatedPremia(params) {
|
|
25247
|
+
const { client, walletClient, account, poolAddress, positionIdList, finalPositionIdList, positionSizes: providedSizes, targets = [], skipPreflight = false, allowForfeit = false, usePremiaAsCollateral = false, builderCode = 0n, txOverrides } = params;
|
|
25248
|
+
if (providedSizes && providedSizes.length !== positionIdList.length) throw new PanopticError("settleAccumulatedPremia: positionSizes length must match positionIdList");
|
|
25249
|
+
const positionSizes = providedSizes ?? await getCurrentPositionSizes({
|
|
25250
|
+
client,
|
|
25251
|
+
poolAddress,
|
|
25252
|
+
account,
|
|
25253
|
+
positionIdList
|
|
25254
|
+
});
|
|
25255
|
+
const heldPositions = finalPositionIdList ?? positionIdList;
|
|
25256
|
+
if (!skipPreflight) {
|
|
25257
|
+
const simulation = await simulateSettle({
|
|
25258
|
+
client,
|
|
25259
|
+
poolAddress,
|
|
25260
|
+
account,
|
|
25261
|
+
positionIdList,
|
|
25262
|
+
finalPositionIdList: heldPositions,
|
|
25263
|
+
positionSizes,
|
|
25264
|
+
targets,
|
|
25265
|
+
usePremiaAsCollateral,
|
|
25266
|
+
builderCode,
|
|
25267
|
+
allowForfeit
|
|
25268
|
+
});
|
|
25269
|
+
if (!simulation.success) throw simulation.error;
|
|
25270
|
+
}
|
|
25271
|
+
const { dispatch: dispatch$1 } = buildProtectedSettlePlan({
|
|
25272
|
+
positionIdList,
|
|
25273
|
+
finalPositionIdList: heldPositions,
|
|
25274
|
+
positionSizes,
|
|
25275
|
+
usePremiaAsCollateral,
|
|
25276
|
+
builderCode
|
|
25277
|
+
});
|
|
25278
|
+
if (targets.length > 0) return executeSettleSequence({
|
|
25279
|
+
client,
|
|
25280
|
+
walletClient,
|
|
25281
|
+
account,
|
|
25282
|
+
poolAddress,
|
|
25283
|
+
positionIdListFrom: heldPositions,
|
|
25284
|
+
targets,
|
|
25285
|
+
dispatch: dispatch$1,
|
|
25286
|
+
txOverrides
|
|
25287
|
+
});
|
|
25288
|
+
return submitWrite({
|
|
25289
|
+
client,
|
|
25290
|
+
walletClient,
|
|
25291
|
+
account,
|
|
25292
|
+
address: poolAddress,
|
|
25293
|
+
abi: panopticPoolV2Abi,
|
|
25294
|
+
functionName: "dispatch",
|
|
25295
|
+
args: [
|
|
25296
|
+
dispatch$1.positionIdList,
|
|
25297
|
+
dispatch$1.finalPositionIdList,
|
|
25298
|
+
dispatch$1.positionSizes,
|
|
25299
|
+
dispatch$1.tickAndSpreadLimits.map((t) => [
|
|
25300
|
+
Number(t[0]),
|
|
25301
|
+
Number(t[1]),
|
|
25302
|
+
Number(t[2])
|
|
25303
|
+
]),
|
|
25304
|
+
dispatch$1.usePremiaAsCollateral,
|
|
25305
|
+
dispatch$1.builderCode
|
|
25306
|
+
],
|
|
25307
|
+
txOverrides
|
|
25308
|
+
});
|
|
25309
|
+
}
|
|
25310
|
+
/**
|
|
25311
|
+
* Settle premia and wait for confirmation.
|
|
25312
|
+
*/
|
|
25313
|
+
async function settleAccumulatedPremiaAndWait(params) {
|
|
25314
|
+
const result = await settleAccumulatedPremia(params);
|
|
25315
|
+
return result.wait();
|
|
25316
|
+
}
|
|
25317
|
+
|
|
25318
|
+
//#endregion
|
|
25319
|
+
//#region src/panoptic/v2/writes/pokeOracle.ts
|
|
25320
|
+
/**
|
|
25321
|
+
* Poke the oracle to update its state.
|
|
25322
|
+
*
|
|
25323
|
+
* This function can be called to advance the oracle epoch.
|
|
25324
|
+
* Note: The oracle can only be poked once per epoch (64 seconds).
|
|
25325
|
+
*
|
|
25326
|
+
* @param params - Poke oracle parameters
|
|
25327
|
+
* @returns TxResult
|
|
25328
|
+
* @throws OracleRateLimitedError if checkRateLimit is true and oracle was recently poked
|
|
25329
|
+
*
|
|
25330
|
+
* @example
|
|
25331
|
+
* ```typescript
|
|
25332
|
+
* const result = await pokeOracle({
|
|
25333
|
+
* client,
|
|
25334
|
+
* walletClient,
|
|
25335
|
+
* account,
|
|
25336
|
+
* poolAddress,
|
|
25337
|
+
* })
|
|
25338
|
+
* const receipt = await result.wait()
|
|
25339
|
+
* ```
|
|
25340
|
+
*/
|
|
25341
|
+
async function pokeOracle(params) {
|
|
25342
|
+
const { client, walletClient, account, poolAddress, checkRateLimit = false, txOverrides } = params;
|
|
25343
|
+
if (checkRateLimit) {
|
|
25344
|
+
const [oracleData, block] = await Promise.all([client.readContract({
|
|
25345
|
+
address: poolAddress,
|
|
25346
|
+
abi: panopticPoolV2Abi,
|
|
25347
|
+
functionName: "getOracleTicks"
|
|
25348
|
+
}), client.getBlock()]);
|
|
25349
|
+
const oraclePack = oracleData[4];
|
|
25350
|
+
const { epoch } = decodeOracleTiming(oraclePack, block.timestamp);
|
|
25351
|
+
const currentEpoch = oracleEpochAt(block.timestamp);
|
|
25352
|
+
if (currentEpoch === epoch) {
|
|
25353
|
+
const lastUpdate = epoch << 6n;
|
|
25354
|
+
throw new OracleRateLimitedError(lastUpdate, block.timestamp);
|
|
25355
|
+
}
|
|
25356
|
+
}
|
|
25357
|
+
return submitWrite({
|
|
25358
|
+
client,
|
|
25359
|
+
walletClient,
|
|
25360
|
+
account,
|
|
25361
|
+
address: poolAddress,
|
|
25362
|
+
abi: panopticPoolV2Abi,
|
|
25363
|
+
functionName: "pokeOracle",
|
|
25364
|
+
args: [],
|
|
25365
|
+
txOverrides
|
|
25366
|
+
});
|
|
25367
|
+
}
|
|
25368
|
+
/**
|
|
25369
|
+
* Poke oracle and wait for confirmation.
|
|
25370
|
+
*/
|
|
25371
|
+
async function pokeOracleAndWait(params) {
|
|
25372
|
+
const result = await pokeOracle(params);
|
|
25373
|
+
return result.wait();
|
|
25374
|
+
}
|
|
25375
|
+
|
|
25376
|
+
//#endregion
|
|
25377
|
+
//#region src/panoptic/v2/writes/factory.ts
|
|
25378
|
+
/**
|
|
25379
|
+
* Deploy a new Panoptic pool via the factory.
|
|
25380
|
+
*
|
|
25381
|
+
* @param params - Deployment parameters (versioned: 'v3' or 'v4')
|
|
25382
|
+
* @returns Transaction result with hash and wait function
|
|
25383
|
+
*/
|
|
25384
|
+
async function deployNewPool(params) {
|
|
25385
|
+
const { client, walletClient, account, factoryAddress, riskEngine, salt, txOverrides } = params;
|
|
25386
|
+
if (params.version === "v3") return submitWrite({
|
|
25387
|
+
client,
|
|
25388
|
+
walletClient,
|
|
25389
|
+
account,
|
|
25390
|
+
address: factoryAddress,
|
|
25391
|
+
abi: panopticFactoryV3Abi,
|
|
25392
|
+
functionName: "deployNewPool",
|
|
25393
|
+
args: [
|
|
25394
|
+
params.token0,
|
|
25395
|
+
params.token1,
|
|
25396
|
+
params.fee,
|
|
25397
|
+
riskEngine,
|
|
25398
|
+
salt
|
|
25399
|
+
],
|
|
25400
|
+
txOverrides
|
|
25401
|
+
});
|
|
25402
|
+
return submitWrite({
|
|
25403
|
+
client,
|
|
25404
|
+
walletClient,
|
|
25405
|
+
account,
|
|
25406
|
+
address: factoryAddress,
|
|
25407
|
+
abi: panopticFactoryV4Abi,
|
|
25408
|
+
functionName: "deployNewPool",
|
|
25409
|
+
args: [
|
|
25410
|
+
{
|
|
25411
|
+
currency0: params.poolKey.currency0,
|
|
25412
|
+
currency1: params.poolKey.currency1,
|
|
25413
|
+
fee: Number(params.poolKey.fee),
|
|
25414
|
+
tickSpacing: Number(params.poolKey.tickSpacing),
|
|
25415
|
+
hooks: params.poolKey.hooks
|
|
25416
|
+
},
|
|
25417
|
+
riskEngine,
|
|
25418
|
+
salt
|
|
25419
|
+
],
|
|
25420
|
+
txOverrides
|
|
25421
|
+
});
|
|
25422
|
+
}
|
|
25423
|
+
/**
|
|
25424
|
+
* Deploy a new Panoptic pool and wait for confirmation.
|
|
25425
|
+
*/
|
|
25426
|
+
async function deployNewPoolAndWait(params) {
|
|
25427
|
+
const result = await deployNewPool(params);
|
|
25428
|
+
return result.wait();
|
|
25429
|
+
}
|
|
25430
|
+
|
|
25431
|
+
//#endregion
|
|
25432
|
+
//#region src/panoptic/v2/writes/txManagement.ts
|
|
25433
|
+
/** Default gas price multiplier for replacement (12.5% bump = minimum for replacement) */
|
|
25434
|
+
const DEFAULT_GAS_PRICE_MULTIPLIER = 1.125;
|
|
25435
|
+
/**
|
|
25436
|
+
* Apply a multiplier to a bigint gas value.
|
|
25437
|
+
* Uses integer arithmetic to avoid floating point issues.
|
|
25438
|
+
*/
|
|
25439
|
+
function applyMultiplier(value, multiplier) {
|
|
25440
|
+
const bps = BigInt(Math.ceil(multiplier * 1e4));
|
|
25441
|
+
return value * bps / 10000n;
|
|
25442
|
+
}
|
|
25443
|
+
/**
|
|
25444
|
+
* Compute bumped gas parameters from the original transaction.
|
|
25445
|
+
*/
|
|
25446
|
+
function computeBumpedGas(originalMaxFeePerGas, originalMaxPriorityFeePerGas, explicitMaxFeePerGas, explicitMaxPriorityFeePerGas, multiplier) {
|
|
25447
|
+
const maxFeePerGas = explicitMaxFeePerGas ?? applyMultiplier(originalMaxFeePerGas ?? 0n, multiplier);
|
|
25448
|
+
const maxPriorityFeePerGas = explicitMaxPriorityFeePerGas ?? applyMultiplier(originalMaxPriorityFeePerGas ?? 0n, multiplier);
|
|
25449
|
+
return {
|
|
25450
|
+
maxFeePerGas,
|
|
25451
|
+
maxPriorityFeePerGas
|
|
25452
|
+
};
|
|
25453
|
+
}
|
|
25454
|
+
/**
|
|
25455
|
+
* Speed up a pending transaction by resubmitting with higher gas.
|
|
25456
|
+
*
|
|
25457
|
+
* Fetches the original transaction, extracts its parameters,
|
|
25458
|
+
* bumps the gas price, and resubmits with the same nonce.
|
|
25459
|
+
*
|
|
24797
25460
|
* @param params - Speed up parameters
|
|
24798
25461
|
* @returns TxResult for the replacement transaction
|
|
24799
25462
|
* @throws Error if the original transaction is not found
|
|
@@ -25783,469 +26446,145 @@ async function smartRepay(params) {
|
|
|
25783
26446
|
client,
|
|
25784
26447
|
walletClient,
|
|
25785
26448
|
account,
|
|
25786
|
-
address: poolAddress,
|
|
25787
|
-
abi: panopticPoolV2Abi,
|
|
25788
|
-
functionName: "dispatch",
|
|
25789
|
-
args: [
|
|
25790
|
-
opsPositionIds,
|
|
25791
|
-
finalPositionIdList,
|
|
25792
|
-
opsSizes,
|
|
25793
|
-
opsLimits,
|
|
25794
|
-
false,
|
|
25795
|
-
builderCode
|
|
25796
|
-
],
|
|
25797
|
-
txOverrides
|
|
25798
|
-
});
|
|
25799
|
-
} catch (error) {
|
|
25800
|
-
if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) continue;
|
|
25801
|
-
throw error;
|
|
25802
|
-
}
|
|
25803
|
-
}
|
|
25804
|
-
throw new MaxRetriesExceededError("smartRepay");
|
|
25805
|
-
}
|
|
25806
|
-
/**
|
|
25807
|
-
* Smart repay and wait for confirmation.
|
|
25808
|
-
*/
|
|
25809
|
-
async function smartRepayAndWait(params) {
|
|
25810
|
-
const result = await smartRepay(params);
|
|
25811
|
-
const receipt = await result.wait();
|
|
25812
|
-
if (params.storage && params.chainId !== void 0) {
|
|
25813
|
-
const { client, account, poolAddress, chainId, token, amount, storage, existingPositionIds } = params;
|
|
25814
|
-
const pool = await getPool({
|
|
25815
|
-
client,
|
|
25816
|
-
poolAddress,
|
|
25817
|
-
chainId
|
|
25818
|
-
});
|
|
25819
|
-
const tokenIndex = resolveTokenIndex(token, pool.collateralTracker0.token, pool.collateralTracker1.token);
|
|
25820
|
-
const loans = await getLoanPositionsForToken(client, poolAddress, account, existingPositionIds, tokenIndex);
|
|
25821
|
-
const loanIds = loans.map((l) => l.tokenId);
|
|
25822
|
-
const totalDebt = loans.reduce((sum, l) => sum + l.tokenAmount, 0n);
|
|
25823
|
-
const remainder = totalDebt > amount ? totalDebt - amount : 0n;
|
|
25824
|
-
const positionIds = existingPositionIds ?? await getTrackedPositionIds({
|
|
25825
|
-
chainId,
|
|
25826
|
-
poolAddress,
|
|
25827
|
-
account,
|
|
25828
|
-
storage
|
|
25829
|
-
});
|
|
25830
|
-
let updatedIds = positionIds.filter((id) => !loanIds.includes(id));
|
|
25831
|
-
if (remainder > 0n) {
|
|
25832
|
-
const nonLoanIds = existingPositionIds.filter((id) => !loanIds.includes(id));
|
|
25833
|
-
const newLoan = buildUniqueLoan(pool.poolId, tokenIndex, tokenIndex, pool.currentTick, pool.tickSpacing, nonLoanIds, remainder);
|
|
25834
|
-
updatedIds = [...updatedIds, newLoan.tokenId];
|
|
25835
|
-
}
|
|
25836
|
-
await savePositionIds(storage, chainId, poolAddress, account, updatedIds);
|
|
25837
|
-
}
|
|
25838
|
-
return receipt;
|
|
25839
|
-
}
|
|
25840
|
-
|
|
25841
|
-
//#endregion
|
|
25842
|
-
//#region src/panoptic/v2/simulations/simulateBatchDispatch.ts
|
|
25843
|
-
/**
|
|
25844
|
-
* Simulate a batch dispatch built from `items` + the current on-chain
|
|
25845
|
-
* positionIdList. Returns batch diagnostics OR a real simulation result.
|
|
25846
|
-
*/
|
|
25847
|
-
async function simulateBatchDispatch(params) {
|
|
25848
|
-
const { client, poolAddress, account, items, existingPositionIds, usePremiaAsCollateral = false, builderCode = 0n, blockNumber } = params;
|
|
25849
|
-
const { args, diagnostics } = buildBatchDispatchArgs({
|
|
25850
|
-
items,
|
|
25851
|
-
existingPositionIds,
|
|
25852
|
-
usePremiaAsCollateral,
|
|
25853
|
-
builderCode
|
|
25854
|
-
});
|
|
25855
|
-
if (args === null) {
|
|
25856
|
-
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
25857
|
-
const meta = await getBlockMeta({
|
|
25858
|
-
client,
|
|
25859
|
-
blockNumber: targetBlockNumber
|
|
25860
|
-
});
|
|
25861
|
-
return {
|
|
25862
|
-
success: false,
|
|
25863
|
-
diagnostics,
|
|
25864
|
-
_meta: meta
|
|
25865
|
-
};
|
|
25866
|
-
}
|
|
25867
|
-
const sim = await simulateDispatch({
|
|
25868
|
-
client,
|
|
25869
|
-
poolAddress,
|
|
25870
|
-
account,
|
|
25871
|
-
positionIdList: args.positionIdList,
|
|
25872
|
-
finalPositionIdList: args.finalPositionIdList,
|
|
25873
|
-
existingPositionIdList: existingPositionIds,
|
|
25874
|
-
positionSizes: args.positionSizes,
|
|
25875
|
-
tickAndSpreadLimits: args.tickAndSpreadLimits,
|
|
25876
|
-
usePremiaAsCollateral: args.usePremiaAsCollateral,
|
|
25877
|
-
builderCode: args.builderCode,
|
|
25878
|
-
blockNumber
|
|
25879
|
-
});
|
|
25880
|
-
return {
|
|
25881
|
-
...sim,
|
|
25882
|
-
diagnostics: []
|
|
25883
|
-
};
|
|
25884
|
-
}
|
|
25885
|
-
|
|
25886
|
-
//#endregion
|
|
25887
|
-
//#region src/panoptic/v2/simulations/simulateClosePosition.ts
|
|
25888
|
-
/**
|
|
25889
|
-
* Simulate closing a position.
|
|
25890
|
-
*
|
|
25891
|
-
* Uses PanopticPool.multicall with getAssetsOf-dispatch-getAssetsOf pattern
|
|
25892
|
-
* to measure exact collateral asset movements from the burn.
|
|
25893
|
-
*
|
|
25894
|
-
* @param params - Simulation parameters
|
|
25895
|
-
* @returns Simulation result with close data or error
|
|
25896
|
-
*/
|
|
25897
|
-
async function simulateClosePosition(params) {
|
|
25898
|
-
const { client, poolAddress, account, positionIdList, tokenId, tickLimitLow, tickLimitHigh, spreadLimit = 0n, swapAtMint = false, usePremiaAsCollateral = false, builderCode = 0n, blockNumber } = params;
|
|
25899
|
-
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
25900
|
-
const metaPromise = getBlockMeta({
|
|
25901
|
-
client,
|
|
25902
|
-
blockNumber: targetBlockNumber
|
|
25903
|
-
});
|
|
25904
|
-
const tickLimits$1 = swapAtMint ? [
|
|
25905
|
-
Number(tickLimitHigh),
|
|
25906
|
-
Number(tickLimitLow),
|
|
25907
|
-
Number(spreadLimit)
|
|
25908
|
-
] : [
|
|
25909
|
-
Number(tickLimitLow),
|
|
25910
|
-
Number(tickLimitHigh),
|
|
25911
|
-
Number(spreadLimit)
|
|
25912
|
-
];
|
|
25913
|
-
try {
|
|
25914
|
-
const finalPositionIdList = positionIdList.filter((id) => id !== tokenId);
|
|
25915
|
-
const callData = encodeFunctionData({
|
|
25916
|
-
abi: panopticPoolV2Abi,
|
|
25917
|
-
functionName: "dispatch",
|
|
25918
|
-
args: [
|
|
25919
|
-
[tokenId],
|
|
25920
|
-
finalPositionIdList,
|
|
25921
|
-
[0n],
|
|
25922
|
-
[tickLimits$1],
|
|
25923
|
-
usePremiaAsCollateral,
|
|
25924
|
-
builderCode
|
|
25925
|
-
]
|
|
25926
|
-
});
|
|
25927
|
-
const flowResult = await simulateWithTokenFlow({
|
|
25928
|
-
client,
|
|
25929
|
-
poolAddress,
|
|
25930
|
-
user: account,
|
|
25931
|
-
callData,
|
|
25932
|
-
blockNumber: targetBlockNumber
|
|
25933
|
-
});
|
|
25934
|
-
if (!flowResult.success || !flowResult.tokenFlow) throw flowResult.rawError ?? new PanopticError(flowResult.error || "Token flow simulation failed");
|
|
25935
|
-
const tokenFlow = flowResult.tokenFlow;
|
|
25936
|
-
const _meta = await metaPromise;
|
|
25937
|
-
const data = {
|
|
25938
|
-
amount0Received: tokenFlow.delta0,
|
|
25939
|
-
amount1Received: tokenFlow.delta1,
|
|
25940
|
-
premiaCollected0: null,
|
|
25941
|
-
premiaCollected1: null,
|
|
25942
|
-
postCollateral0: tokenFlow.balanceAfter0,
|
|
25943
|
-
postCollateral1: tokenFlow.balanceAfter1,
|
|
25944
|
-
realizedPnL0: null,
|
|
25945
|
-
realizedPnL1: null
|
|
25946
|
-
};
|
|
25947
|
-
return {
|
|
25948
|
-
success: true,
|
|
25949
|
-
data,
|
|
25950
|
-
gasEstimate: flowResult.gasEstimate,
|
|
25951
|
-
tokenFlow,
|
|
25952
|
-
_meta
|
|
25953
|
-
};
|
|
25954
|
-
} catch (error) {
|
|
25955
|
-
const _meta = await metaPromise;
|
|
25956
|
-
return {
|
|
25957
|
-
success: false,
|
|
25958
|
-
error: error instanceof PanopticError ? error : new PanopticError(error instanceof Error ? error.message : "Simulation failed", error instanceof Error ? error : void 0),
|
|
25959
|
-
_meta
|
|
25960
|
-
};
|
|
26449
|
+
address: poolAddress,
|
|
26450
|
+
abi: panopticPoolV2Abi,
|
|
26451
|
+
functionName: "dispatch",
|
|
26452
|
+
args: [
|
|
26453
|
+
opsPositionIds,
|
|
26454
|
+
finalPositionIdList,
|
|
26455
|
+
opsSizes,
|
|
26456
|
+
opsLimits,
|
|
26457
|
+
false,
|
|
26458
|
+
builderCode
|
|
26459
|
+
],
|
|
26460
|
+
txOverrides
|
|
26461
|
+
});
|
|
26462
|
+
} catch (error) {
|
|
26463
|
+
if (isInputListFailError(error) && attempt < MAX_RETRIES - 1) continue;
|
|
26464
|
+
throw error;
|
|
26465
|
+
}
|
|
25961
26466
|
}
|
|
26467
|
+
throw new MaxRetriesExceededError("smartRepay");
|
|
25962
26468
|
}
|
|
25963
|
-
|
|
25964
|
-
//#endregion
|
|
25965
|
-
//#region src/panoptic/v2/simulations/simulateForceExercise.ts
|
|
25966
26469
|
/**
|
|
25967
|
-
*
|
|
25968
|
-
*
|
|
25969
|
-
* @param params - Simulation parameters
|
|
25970
|
-
* @returns Simulation result with exercise data or error
|
|
26470
|
+
* Smart repay and wait for confirmation.
|
|
25971
26471
|
*/
|
|
25972
|
-
async function
|
|
25973
|
-
const
|
|
25974
|
-
const
|
|
25975
|
-
|
|
25976
|
-
client,
|
|
25977
|
-
|
|
25978
|
-
});
|
|
25979
|
-
const emptyTokenFlow = {
|
|
25980
|
-
delta0: 0n,
|
|
25981
|
-
delta1: 0n,
|
|
25982
|
-
balanceBefore0: 0n,
|
|
25983
|
-
balanceBefore1: 0n,
|
|
25984
|
-
balanceAfter0: 0n,
|
|
25985
|
-
balanceAfter1: 0n,
|
|
25986
|
-
tickBefore: null,
|
|
25987
|
-
tickAfter: null
|
|
25988
|
-
};
|
|
25989
|
-
try {
|
|
25990
|
-
const callData = encodeFunctionData({
|
|
25991
|
-
abi: panopticPoolV2Abi,
|
|
25992
|
-
functionName: "dispatchFrom",
|
|
25993
|
-
args: [
|
|
25994
|
-
positionIdListFrom,
|
|
25995
|
-
user,
|
|
25996
|
-
positionIdListTo,
|
|
25997
|
-
positionIdListToFinal,
|
|
25998
|
-
0n
|
|
25999
|
-
]
|
|
26000
|
-
});
|
|
26001
|
-
const flowResult = await simulateWithTokenFlow({
|
|
26472
|
+
async function smartRepayAndWait(params) {
|
|
26473
|
+
const result = await smartRepay(params);
|
|
26474
|
+
const receipt = await result.wait();
|
|
26475
|
+
if (params.storage && params.chainId !== void 0) {
|
|
26476
|
+
const { client, account, poolAddress, chainId, token, amount, storage, existingPositionIds } = params;
|
|
26477
|
+
const pool = await getPool({
|
|
26002
26478
|
client,
|
|
26003
26479
|
poolAddress,
|
|
26004
|
-
|
|
26005
|
-
callData,
|
|
26006
|
-
blockNumber: targetBlockNumber
|
|
26480
|
+
chainId
|
|
26007
26481
|
});
|
|
26008
|
-
|
|
26009
|
-
|
|
26010
|
-
|
|
26011
|
-
|
|
26012
|
-
|
|
26013
|
-
|
|
26014
|
-
|
|
26015
|
-
|
|
26016
|
-
|
|
26017
|
-
|
|
26018
|
-
|
|
26019
|
-
|
|
26020
|
-
|
|
26021
|
-
|
|
26022
|
-
|
|
26023
|
-
|
|
26024
|
-
_meta: _meta$1
|
|
26025
|
-
};
|
|
26026
|
-
}
|
|
26027
|
-
throw new PanopticError(errorMessage);
|
|
26028
|
-
}
|
|
26029
|
-
const _meta = await metaPromise;
|
|
26030
|
-
const tokenFlow = flowResult.tokenFlow;
|
|
26031
|
-
const data = {
|
|
26032
|
-
exerciseFee0: tokenFlow.delta0,
|
|
26033
|
-
exerciseFee1: tokenFlow.delta1,
|
|
26034
|
-
canExercise: true
|
|
26035
|
-
};
|
|
26036
|
-
return {
|
|
26037
|
-
success: true,
|
|
26038
|
-
data,
|
|
26039
|
-
gasEstimate: flowResult.gasEstimate,
|
|
26040
|
-
tokenFlow,
|
|
26041
|
-
_meta
|
|
26042
|
-
};
|
|
26043
|
-
} catch (error) {
|
|
26044
|
-
const _meta = await metaPromise;
|
|
26045
|
-
const errorMessage = error instanceof Error ? error.message : "Simulation failed";
|
|
26046
|
-
const isNotExercisable = errorMessage.includes("NoLegsExercisable") || errorMessage.includes("NotALongLeg");
|
|
26047
|
-
if (isNotExercisable) {
|
|
26048
|
-
const data = {
|
|
26049
|
-
exerciseFee0: 0n,
|
|
26050
|
-
exerciseFee1: 0n,
|
|
26051
|
-
canExercise: false,
|
|
26052
|
-
reason: errorMessage.includes("NoLegsExercisable") ? "No legs are exercisable (not ITM)" : "Position does not have a long leg"
|
|
26053
|
-
};
|
|
26054
|
-
return {
|
|
26055
|
-
success: true,
|
|
26056
|
-
data,
|
|
26057
|
-
gasEstimate: 0n,
|
|
26058
|
-
tokenFlow: emptyTokenFlow,
|
|
26059
|
-
_meta
|
|
26060
|
-
};
|
|
26482
|
+
const tokenIndex = resolveTokenIndex(token, pool.collateralTracker0.token, pool.collateralTracker1.token);
|
|
26483
|
+
const loans = await getLoanPositionsForToken(client, poolAddress, account, existingPositionIds, tokenIndex);
|
|
26484
|
+
const loanIds = loans.map((l) => l.tokenId);
|
|
26485
|
+
const totalDebt = loans.reduce((sum, l) => sum + l.tokenAmount, 0n);
|
|
26486
|
+
const remainder = totalDebt > amount ? totalDebt - amount : 0n;
|
|
26487
|
+
const positionIds = existingPositionIds ?? await getTrackedPositionIds({
|
|
26488
|
+
chainId,
|
|
26489
|
+
poolAddress,
|
|
26490
|
+
account,
|
|
26491
|
+
storage
|
|
26492
|
+
});
|
|
26493
|
+
let updatedIds = positionIds.filter((id) => !loanIds.includes(id));
|
|
26494
|
+
if (remainder > 0n) {
|
|
26495
|
+
const nonLoanIds = existingPositionIds.filter((id) => !loanIds.includes(id));
|
|
26496
|
+
const newLoan = buildUniqueLoan(pool.poolId, tokenIndex, tokenIndex, pool.currentTick, pool.tickSpacing, nonLoanIds, remainder);
|
|
26497
|
+
updatedIds = [...updatedIds, newLoan.tokenId];
|
|
26061
26498
|
}
|
|
26062
|
-
|
|
26063
|
-
success: false,
|
|
26064
|
-
error: error instanceof PanopticError ? error : new PanopticError(errorMessage, error instanceof Error ? error : void 0),
|
|
26065
|
-
_meta
|
|
26066
|
-
};
|
|
26499
|
+
await savePositionIds(storage, chainId, poolAddress, account, updatedIds);
|
|
26067
26500
|
}
|
|
26501
|
+
return receipt;
|
|
26068
26502
|
}
|
|
26069
26503
|
|
|
26070
26504
|
//#endregion
|
|
26071
|
-
//#region src/panoptic/v2/simulations/
|
|
26505
|
+
//#region src/panoptic/v2/simulations/simulateBatchDispatch.ts
|
|
26072
26506
|
/**
|
|
26073
|
-
* Simulate a
|
|
26074
|
-
*
|
|
26075
|
-
* @param params - Simulation parameters
|
|
26076
|
-
* @returns Simulation result with liquidation data or error
|
|
26507
|
+
* Simulate a batch dispatch built from `items` + the current on-chain
|
|
26508
|
+
* positionIdList. Returns batch diagnostics OR a real simulation result.
|
|
26077
26509
|
*/
|
|
26078
|
-
async function
|
|
26079
|
-
const { client, poolAddress, account,
|
|
26080
|
-
const
|
|
26081
|
-
|
|
26082
|
-
|
|
26083
|
-
|
|
26510
|
+
async function simulateBatchDispatch(params) {
|
|
26511
|
+
const { client, poolAddress, account, items, existingPositionIds, usePremiaAsCollateral = false, builderCode = 0n, blockNumber } = params;
|
|
26512
|
+
const { args, diagnostics } = buildBatchDispatchArgs({
|
|
26513
|
+
items,
|
|
26514
|
+
existingPositionIds,
|
|
26515
|
+
usePremiaAsCollateral,
|
|
26516
|
+
builderCode
|
|
26084
26517
|
});
|
|
26085
|
-
|
|
26086
|
-
|
|
26087
|
-
|
|
26088
|
-
|
|
26089
|
-
|
|
26090
|
-
|
|
26091
|
-
balanceAfter1: 0n,
|
|
26092
|
-
tickBefore: null,
|
|
26093
|
-
tickAfter: null
|
|
26094
|
-
};
|
|
26095
|
-
try {
|
|
26096
|
-
const callData = encodeFunctionData({
|
|
26097
|
-
abi: panopticPoolV2Abi,
|
|
26098
|
-
functionName: "dispatchFrom",
|
|
26099
|
-
args: [
|
|
26100
|
-
positionIdListFrom,
|
|
26101
|
-
liquidatee,
|
|
26102
|
-
positionIdListTo,
|
|
26103
|
-
positionIdListToFinal,
|
|
26104
|
-
0n
|
|
26105
|
-
]
|
|
26106
|
-
});
|
|
26107
|
-
const flowResult = await simulateWithTokenFlow({
|
|
26108
|
-
client,
|
|
26109
|
-
poolAddress,
|
|
26110
|
-
user: account,
|
|
26111
|
-
callData,
|
|
26112
|
-
blockNumber: targetBlockNumber
|
|
26113
|
-
});
|
|
26114
|
-
if (!flowResult.success || !flowResult.tokenFlow) {
|
|
26115
|
-
const errorMessage = flowResult.error || "Simulation failed";
|
|
26116
|
-
const isNotLiquidatable = errorMessage.includes("NotMarginCalled") || errorMessage.includes("AccountInsolvent");
|
|
26117
|
-
if (isNotLiquidatable) {
|
|
26118
|
-
const _meta$1 = await metaPromise;
|
|
26119
|
-
const data$1 = {
|
|
26120
|
-
bonus0: 0n,
|
|
26121
|
-
bonus1: 0n,
|
|
26122
|
-
positionsClosed: [],
|
|
26123
|
-
isLiquidatable: false,
|
|
26124
|
-
shortfall0: 0n,
|
|
26125
|
-
shortfall1: 0n
|
|
26126
|
-
};
|
|
26127
|
-
return {
|
|
26128
|
-
success: true,
|
|
26129
|
-
data: data$1,
|
|
26130
|
-
gasEstimate: 0n,
|
|
26131
|
-
tokenFlow: emptyTokenFlow,
|
|
26132
|
-
_meta: _meta$1
|
|
26133
|
-
};
|
|
26134
|
-
}
|
|
26135
|
-
throw new PanopticError(errorMessage);
|
|
26136
|
-
}
|
|
26137
|
-
const _meta = await metaPromise;
|
|
26138
|
-
const tokenFlow = flowResult.tokenFlow;
|
|
26139
|
-
const positionsClosed = positionIdListTo.filter((id) => !positionIdListToFinal.includes(id));
|
|
26140
|
-
const data = {
|
|
26141
|
-
bonus0: tokenFlow.delta0 > 0n ? tokenFlow.delta0 : 0n,
|
|
26142
|
-
bonus1: tokenFlow.delta1 > 0n ? tokenFlow.delta1 : 0n,
|
|
26143
|
-
positionsClosed,
|
|
26144
|
-
isLiquidatable: true,
|
|
26145
|
-
shortfall0: 0n,
|
|
26146
|
-
shortfall1: 0n
|
|
26147
|
-
};
|
|
26148
|
-
return {
|
|
26149
|
-
success: true,
|
|
26150
|
-
data,
|
|
26151
|
-
gasEstimate: flowResult.gasEstimate,
|
|
26152
|
-
tokenFlow,
|
|
26153
|
-
_meta
|
|
26154
|
-
};
|
|
26155
|
-
} catch (error) {
|
|
26156
|
-
const _meta = await metaPromise;
|
|
26157
|
-
const errorMessage = error instanceof Error ? error.message : "Simulation failed";
|
|
26158
|
-
const isNotLiquidatable = errorMessage.includes("NotMarginCalled") || errorMessage.includes("AccountInsolvent");
|
|
26159
|
-
if (isNotLiquidatable) {
|
|
26160
|
-
const data = {
|
|
26161
|
-
bonus0: 0n,
|
|
26162
|
-
bonus1: 0n,
|
|
26163
|
-
positionsClosed: [],
|
|
26164
|
-
isLiquidatable: false,
|
|
26165
|
-
shortfall0: 0n,
|
|
26166
|
-
shortfall1: 0n
|
|
26167
|
-
};
|
|
26168
|
-
return {
|
|
26169
|
-
success: true,
|
|
26170
|
-
data,
|
|
26171
|
-
gasEstimate: 0n,
|
|
26172
|
-
tokenFlow: emptyTokenFlow,
|
|
26173
|
-
_meta
|
|
26174
|
-
};
|
|
26175
|
-
}
|
|
26518
|
+
if (args === null) {
|
|
26519
|
+
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
26520
|
+
const meta = await getBlockMeta({
|
|
26521
|
+
client,
|
|
26522
|
+
blockNumber: targetBlockNumber
|
|
26523
|
+
});
|
|
26176
26524
|
return {
|
|
26177
26525
|
success: false,
|
|
26178
|
-
|
|
26179
|
-
_meta
|
|
26526
|
+
diagnostics,
|
|
26527
|
+
_meta: meta
|
|
26180
26528
|
};
|
|
26181
26529
|
}
|
|
26530
|
+
const sim = await simulateDispatch({
|
|
26531
|
+
client,
|
|
26532
|
+
poolAddress,
|
|
26533
|
+
account,
|
|
26534
|
+
positionIdList: args.positionIdList,
|
|
26535
|
+
finalPositionIdList: args.finalPositionIdList,
|
|
26536
|
+
existingPositionIdList: existingPositionIds,
|
|
26537
|
+
positionSizes: args.positionSizes,
|
|
26538
|
+
tickAndSpreadLimits: args.tickAndSpreadLimits,
|
|
26539
|
+
usePremiaAsCollateral: args.usePremiaAsCollateral,
|
|
26540
|
+
builderCode: args.builderCode,
|
|
26541
|
+
blockNumber
|
|
26542
|
+
});
|
|
26543
|
+
return {
|
|
26544
|
+
...sim,
|
|
26545
|
+
diagnostics: []
|
|
26546
|
+
};
|
|
26182
26547
|
}
|
|
26183
26548
|
|
|
26184
26549
|
//#endregion
|
|
26185
|
-
//#region src/panoptic/v2/simulations/
|
|
26186
|
-
/** BIT_MASK_128 = (1n << 128n) - 1n */
|
|
26187
|
-
const BIT_MASK_128 = (1n << 128n) - 1n;
|
|
26188
|
-
/**
|
|
26189
|
-
* PanopticPool multicall ABI (inherited from Uniswap).
|
|
26190
|
-
*/
|
|
26191
|
-
const multicallAbi = [{
|
|
26192
|
-
type: "function",
|
|
26193
|
-
name: "multicall",
|
|
26194
|
-
inputs: [{
|
|
26195
|
-
name: "data",
|
|
26196
|
-
type: "bytes[]"
|
|
26197
|
-
}],
|
|
26198
|
-
outputs: [{
|
|
26199
|
-
name: "results",
|
|
26200
|
-
type: "bytes[]"
|
|
26201
|
-
}],
|
|
26202
|
-
stateMutability: "nonpayable"
|
|
26203
|
-
}];
|
|
26550
|
+
//#region src/panoptic/v2/simulations/simulateClosePosition.ts
|
|
26204
26551
|
/**
|
|
26205
|
-
* Simulate
|
|
26552
|
+
* Simulate closing a position.
|
|
26206
26553
|
*
|
|
26207
|
-
*
|
|
26208
|
-
*
|
|
26209
|
-
* in a single multicall.
|
|
26554
|
+
* Uses PanopticPool.multicall with getAssetsOf-dispatch-getAssetsOf pattern
|
|
26555
|
+
* to measure exact collateral asset movements from the burn.
|
|
26210
26556
|
*
|
|
26211
26557
|
* @param params - Simulation parameters
|
|
26212
|
-
* @returns Simulation result with
|
|
26558
|
+
* @returns Simulation result with close data or error
|
|
26213
26559
|
*/
|
|
26214
|
-
async function
|
|
26215
|
-
const { client, poolAddress, account, positionIdList,
|
|
26560
|
+
async function simulateClosePosition(params) {
|
|
26561
|
+
const { client, poolAddress, account, positionIdList, tokenId, tickLimitLow, tickLimitHigh, spreadLimit = 0n, swapAtMint = false, usePremiaAsCollateral = false, builderCode = 0n, blockNumber } = params;
|
|
26216
26562
|
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
26217
26563
|
const metaPromise = getBlockMeta({
|
|
26218
26564
|
client,
|
|
26219
26565
|
blockNumber: targetBlockNumber
|
|
26220
26566
|
});
|
|
26567
|
+
const tickLimits$1 = swapAtMint ? [
|
|
26568
|
+
Number(tickLimitHigh),
|
|
26569
|
+
Number(tickLimitLow),
|
|
26570
|
+
Number(spreadLimit)
|
|
26571
|
+
] : [
|
|
26572
|
+
Number(tickLimitLow),
|
|
26573
|
+
Number(tickLimitHigh),
|
|
26574
|
+
Number(spreadLimit)
|
|
26575
|
+
];
|
|
26221
26576
|
try {
|
|
26222
|
-
|
|
26223
|
-
const positionSizes = providedSizes ?? await getCurrentPositionSizes({
|
|
26224
|
-
client,
|
|
26225
|
-
poolAddress,
|
|
26226
|
-
account,
|
|
26227
|
-
positionIdList,
|
|
26228
|
-
blockNumber: targetBlockNumber
|
|
26229
|
-
});
|
|
26230
|
-
const tickAndSpreadLimits = positionIdList.map(() => [
|
|
26231
|
-
-887272n,
|
|
26232
|
-
887272n,
|
|
26233
|
-
0n
|
|
26234
|
-
]);
|
|
26577
|
+
const finalPositionIdList = positionIdList.filter((id) => id !== tokenId);
|
|
26235
26578
|
const callData = encodeFunctionData({
|
|
26236
26579
|
abi: panopticPoolV2Abi,
|
|
26237
26580
|
functionName: "dispatch",
|
|
26238
26581
|
args: [
|
|
26239
|
-
|
|
26240
|
-
finalPositionIdList
|
|
26241
|
-
|
|
26242
|
-
|
|
26243
|
-
|
|
26244
|
-
|
|
26245
|
-
Number(t[2])
|
|
26246
|
-
]),
|
|
26247
|
-
false,
|
|
26248
|
-
0n
|
|
26582
|
+
[tokenId],
|
|
26583
|
+
finalPositionIdList,
|
|
26584
|
+
[0n],
|
|
26585
|
+
[tickLimits$1],
|
|
26586
|
+
usePremiaAsCollateral,
|
|
26587
|
+
builderCode
|
|
26249
26588
|
]
|
|
26250
26589
|
});
|
|
26251
26590
|
const flowResult = await simulateWithTokenFlow({
|
|
@@ -26257,23 +26596,16 @@ async function simulateSettle(params) {
|
|
|
26257
26596
|
});
|
|
26258
26597
|
if (!flowResult.success || !flowResult.tokenFlow) throw flowResult.rawError ?? new PanopticError(flowResult.error || "Token flow simulation failed");
|
|
26259
26598
|
const tokenFlow = flowResult.tokenFlow;
|
|
26260
|
-
let forfeitAmounts;
|
|
26261
|
-
if (tokenId !== void 0) forfeitAmounts = await computeForfeitAmounts({
|
|
26262
|
-
client,
|
|
26263
|
-
poolAddress,
|
|
26264
|
-
account,
|
|
26265
|
-
positionIdList,
|
|
26266
|
-
tokenId,
|
|
26267
|
-
dispatchCallData: callData,
|
|
26268
|
-
blockNumber: targetBlockNumber
|
|
26269
|
-
});
|
|
26270
26599
|
const _meta = await metaPromise;
|
|
26271
26600
|
const data = {
|
|
26272
|
-
|
|
26273
|
-
|
|
26601
|
+
amount0Received: tokenFlow.delta0,
|
|
26602
|
+
amount1Received: tokenFlow.delta1,
|
|
26603
|
+
premiaCollected0: null,
|
|
26604
|
+
premiaCollected1: null,
|
|
26274
26605
|
postCollateral0: tokenFlow.balanceAfter0,
|
|
26275
26606
|
postCollateral1: tokenFlow.balanceAfter1,
|
|
26276
|
-
|
|
26607
|
+
realizedPnL0: null,
|
|
26608
|
+
realizedPnL1: null
|
|
26277
26609
|
};
|
|
26278
26610
|
return {
|
|
26279
26611
|
success: true,
|
|
@@ -26291,95 +26623,17 @@ async function simulateSettle(params) {
|
|
|
26291
26623
|
};
|
|
26292
26624
|
}
|
|
26293
26625
|
}
|
|
26294
|
-
/**
|
|
26295
|
-
* Compute forfeit amounts by chaining dispatch + getFullPositionsData
|
|
26296
|
-
* in a single PanopticPool.multicall.
|
|
26297
|
-
*/
|
|
26298
|
-
async function computeForfeitAmounts(params) {
|
|
26299
|
-
const { client, poolAddress, account, tokenId, dispatchCallData, blockNumber } = params;
|
|
26300
|
-
const feesCallAvailable = encodeFunctionData({
|
|
26301
|
-
abi: panopticPoolV2Abi,
|
|
26302
|
-
functionName: "getFullPositionsData",
|
|
26303
|
-
args: [
|
|
26304
|
-
account,
|
|
26305
|
-
false,
|
|
26306
|
-
[tokenId]
|
|
26307
|
-
]
|
|
26308
|
-
});
|
|
26309
|
-
const feesCallTotal = encodeFunctionData({
|
|
26310
|
-
abi: panopticPoolV2Abi,
|
|
26311
|
-
functionName: "getFullPositionsData",
|
|
26312
|
-
args: [
|
|
26313
|
-
account,
|
|
26314
|
-
true,
|
|
26315
|
-
[tokenId]
|
|
26316
|
-
]
|
|
26317
|
-
});
|
|
26318
|
-
try {
|
|
26319
|
-
const { result } = await client.simulateContract({
|
|
26320
|
-
address: poolAddress,
|
|
26321
|
-
abi: multicallAbi,
|
|
26322
|
-
functionName: "multicall",
|
|
26323
|
-
args: [[
|
|
26324
|
-
dispatchCallData,
|
|
26325
|
-
feesCallAvailable,
|
|
26326
|
-
feesCallTotal
|
|
26327
|
-
]],
|
|
26328
|
-
account,
|
|
26329
|
-
blockNumber
|
|
26330
|
-
});
|
|
26331
|
-
const decodeFeesResult = (data) => {
|
|
26332
|
-
return decodeFunctionResult({
|
|
26333
|
-
abi: panopticPoolV2Abi,
|
|
26334
|
-
functionName: "getFullPositionsData",
|
|
26335
|
-
data
|
|
26336
|
-
})[0];
|
|
26337
|
-
};
|
|
26338
|
-
const availablePremium = decodeFeesResult(result[1]);
|
|
26339
|
-
const totalPremium = decodeFeesResult(result[2]);
|
|
26340
|
-
const available0 = availablePremium & BIT_MASK_128;
|
|
26341
|
-
const available1 = availablePremium >> 128n;
|
|
26342
|
-
const total0 = totalPremium & BIT_MASK_128;
|
|
26343
|
-
const total1 = totalPremium >> 128n;
|
|
26344
|
-
return [total0 - available0, total1 - available1];
|
|
26345
|
-
} catch (error) {
|
|
26346
|
-
throw new PanopticError("Forfeit amount computation failed", error instanceof Error ? error : void 0);
|
|
26347
|
-
}
|
|
26348
|
-
}
|
|
26349
26626
|
|
|
26350
26627
|
//#endregion
|
|
26351
|
-
//#region src/panoptic/v2/simulations/
|
|
26352
|
-
/** Soft-failure revert markers for settle premium (target-state issues, not caller errors). */
|
|
26353
|
-
const SOFT_FAILURES = [
|
|
26354
|
-
{
|
|
26355
|
-
marker: "AccountInsolvent",
|
|
26356
|
-
reason: "Target account is insolvent; premium cannot be settled"
|
|
26357
|
-
},
|
|
26358
|
-
{
|
|
26359
|
-
marker: "PositionNotOwned",
|
|
26360
|
-
reason: "Target account no longer owns the position"
|
|
26361
|
-
},
|
|
26362
|
-
{
|
|
26363
|
-
marker: "StaleOracle",
|
|
26364
|
-
reason: "Oracle price is stale; settlement temporarily unavailable"
|
|
26365
|
-
},
|
|
26366
|
-
{
|
|
26367
|
-
marker: "InputListFail",
|
|
26368
|
-
reason: "Position list is stale (target positions changed)"
|
|
26369
|
-
}
|
|
26370
|
-
];
|
|
26628
|
+
//#region src/panoptic/v2/simulations/simulateForceExercise.ts
|
|
26371
26629
|
/**
|
|
26372
|
-
* Simulate
|
|
26373
|
-
* (equal-length `positionIdListTo`/`positionIdListToFinal` selects the settle mode).
|
|
26374
|
-
*
|
|
26375
|
-
* The measured token flow is the CALLER's collateral delta — i.e. the premium
|
|
26376
|
-
* the caller receives from the settlement (for chunks they sold).
|
|
26630
|
+
* Simulate a force exercise operation.
|
|
26377
26631
|
*
|
|
26378
26632
|
* @param params - Simulation parameters
|
|
26379
|
-
* @returns Simulation result with
|
|
26633
|
+
* @returns Simulation result with exercise data or error
|
|
26380
26634
|
*/
|
|
26381
|
-
async function
|
|
26382
|
-
const { client, poolAddress, account, user, positionIdListFrom,
|
|
26635
|
+
async function simulateForceExercise(params) {
|
|
26636
|
+
const { client, poolAddress, account, user, positionIdListFrom, positionIdListTo, positionIdListToFinal, blockNumber } = params;
|
|
26383
26637
|
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
26384
26638
|
const metaPromise = getBlockMeta({
|
|
26385
26639
|
client,
|
|
@@ -26395,115 +26649,52 @@ async function simulateSettlePremiumFrom(params) {
|
|
|
26395
26649
|
tickBefore: null,
|
|
26396
26650
|
tickAfter: null
|
|
26397
26651
|
};
|
|
26398
|
-
const softFailure = (errorMessage) => {
|
|
26399
|
-
const match = SOFT_FAILURES.find(({ marker }) => errorMessage.includes(marker));
|
|
26400
|
-
return match ? {
|
|
26401
|
-
premium0: 0n,
|
|
26402
|
-
premium1: 0n,
|
|
26403
|
-
settled0: 0n,
|
|
26404
|
-
settled1: 0n,
|
|
26405
|
-
canSettle: false,
|
|
26406
|
-
reason: match.reason
|
|
26407
|
-
} : null;
|
|
26408
|
-
};
|
|
26409
26652
|
try {
|
|
26410
|
-
const orderedList = tokenId !== void 0 ? orderListForSettle(positionIdList, tokenId) : positionIdList;
|
|
26411
26653
|
const callData = encodeFunctionData({
|
|
26412
26654
|
abi: panopticPoolV2Abi,
|
|
26413
26655
|
functionName: "dispatchFrom",
|
|
26414
26656
|
args: [
|
|
26415
26657
|
positionIdListFrom,
|
|
26416
26658
|
user,
|
|
26417
|
-
|
|
26418
|
-
|
|
26659
|
+
positionIdListTo,
|
|
26660
|
+
positionIdListToFinal,
|
|
26419
26661
|
0n
|
|
26420
26662
|
]
|
|
26421
26663
|
});
|
|
26422
|
-
const availablePremiumCallData = encodeFunctionData({
|
|
26423
|
-
abi: panopticPoolV2Abi,
|
|
26424
|
-
functionName: "getFullPositionsData",
|
|
26425
|
-
args: [
|
|
26426
|
-
account,
|
|
26427
|
-
false,
|
|
26428
|
-
positionIdListFrom
|
|
26429
|
-
]
|
|
26430
|
-
});
|
|
26431
|
-
const buyerOwedCallData = encodeFunctionData({
|
|
26432
|
-
abi: panopticPoolV2Abi,
|
|
26433
|
-
functionName: "getFullPositionsData",
|
|
26434
|
-
args: [
|
|
26435
|
-
user,
|
|
26436
|
-
true,
|
|
26437
|
-
orderedList
|
|
26438
|
-
]
|
|
26439
|
-
});
|
|
26440
26664
|
const flowResult = await simulateWithTokenFlow({
|
|
26441
26665
|
client,
|
|
26442
26666
|
poolAddress,
|
|
26443
26667
|
user: account,
|
|
26444
26668
|
callData,
|
|
26445
|
-
blockNumber: targetBlockNumber
|
|
26446
|
-
preCallData: [availablePremiumCallData, buyerOwedCallData],
|
|
26447
|
-
postCallData: [availablePremiumCallData, buyerOwedCallData]
|
|
26669
|
+
blockNumber: targetBlockNumber
|
|
26448
26670
|
});
|
|
26449
26671
|
if (!flowResult.success || !flowResult.tokenFlow) {
|
|
26450
26672
|
const errorMessage = flowResult.error || "Simulation failed";
|
|
26451
|
-
const
|
|
26452
|
-
if (
|
|
26673
|
+
const isNotExercisable = errorMessage.includes("NoLegsExercisable") || errorMessage.includes("NotALongLeg");
|
|
26674
|
+
if (isNotExercisable) {
|
|
26453
26675
|
const _meta$1 = await metaPromise;
|
|
26676
|
+
const data$1 = {
|
|
26677
|
+
exerciseFee0: 0n,
|
|
26678
|
+
exerciseFee1: 0n,
|
|
26679
|
+
canExercise: false,
|
|
26680
|
+
reason: errorMessage.includes("NoLegsExercisable") ? "No legs are exercisable (not ITM)" : "Position does not have a long leg"
|
|
26681
|
+
};
|
|
26454
26682
|
return {
|
|
26455
26683
|
success: true,
|
|
26456
|
-
data:
|
|
26457
|
-
gasEstimate: 0n,
|
|
26458
|
-
tokenFlow: emptyTokenFlow,
|
|
26459
|
-
_meta: _meta$1
|
|
26460
|
-
};
|
|
26461
|
-
}
|
|
26462
|
-
throw new PanopticError(errorMessage);
|
|
26463
|
-
}
|
|
26464
|
-
const _meta = await metaPromise;
|
|
26465
|
-
const tokenFlow = flowResult.tokenFlow;
|
|
26466
|
-
const decodePremia = (raw) => {
|
|
26467
|
-
const [shortPremiumPacked, longPremiumPacked] = decodeFunctionResult({
|
|
26468
|
-
abi: panopticPoolV2Abi,
|
|
26469
|
-
functionName: "getFullPositionsData",
|
|
26470
|
-
data: raw
|
|
26471
|
-
});
|
|
26472
|
-
const short = decodeLeftRightUnsigned(shortPremiumPacked);
|
|
26473
|
-
const long = decodeLeftRightUnsigned(longPremiumPacked);
|
|
26474
|
-
return {
|
|
26475
|
-
short0: short.right,
|
|
26476
|
-
short1: short.left,
|
|
26477
|
-
long0: long.right,
|
|
26478
|
-
long1: long.left
|
|
26479
|
-
};
|
|
26480
|
-
};
|
|
26481
|
-
let premium0 = 0n;
|
|
26482
|
-
let premium1 = 0n;
|
|
26483
|
-
const preRaw = flowResult.preCallResults?.[0];
|
|
26484
|
-
const postRaw = flowResult.postCallResults?.[0];
|
|
26485
|
-
if (preRaw !== void 0 && postRaw !== void 0) {
|
|
26486
|
-
const pre = decodePremia(preRaw);
|
|
26487
|
-
const post = decodePremia(postRaw);
|
|
26488
|
-
premium0 = post.short0 > pre.short0 ? post.short0 - pre.short0 : 0n;
|
|
26489
|
-
premium1 = post.short1 > pre.short1 ? post.short1 - pre.short1 : 0n;
|
|
26490
|
-
}
|
|
26491
|
-
let settled0 = 0n;
|
|
26492
|
-
let settled1 = 0n;
|
|
26493
|
-
const preBuyerRaw = flowResult.preCallResults?.[1];
|
|
26494
|
-
const postBuyerRaw = flowResult.postCallResults?.[1];
|
|
26495
|
-
if (preBuyerRaw !== void 0 && postBuyerRaw !== void 0) {
|
|
26496
|
-
const pre = decodePremia(preBuyerRaw);
|
|
26497
|
-
const post = decodePremia(postBuyerRaw);
|
|
26498
|
-
settled0 = pre.long0 > post.long0 ? pre.long0 - post.long0 : 0n;
|
|
26499
|
-
settled1 = pre.long1 > post.long1 ? pre.long1 - post.long1 : 0n;
|
|
26684
|
+
data: data$1,
|
|
26685
|
+
gasEstimate: 0n,
|
|
26686
|
+
tokenFlow: emptyTokenFlow,
|
|
26687
|
+
_meta: _meta$1
|
|
26688
|
+
};
|
|
26689
|
+
}
|
|
26690
|
+
throw new PanopticError(errorMessage);
|
|
26500
26691
|
}
|
|
26692
|
+
const _meta = await metaPromise;
|
|
26693
|
+
const tokenFlow = flowResult.tokenFlow;
|
|
26501
26694
|
const data = {
|
|
26502
|
-
|
|
26503
|
-
|
|
26504
|
-
|
|
26505
|
-
settled1,
|
|
26506
|
-
canSettle: true
|
|
26695
|
+
exerciseFee0: tokenFlow.delta0,
|
|
26696
|
+
exerciseFee1: tokenFlow.delta1,
|
|
26697
|
+
canExercise: true
|
|
26507
26698
|
};
|
|
26508
26699
|
return {
|
|
26509
26700
|
success: true,
|
|
@@ -26515,14 +26706,22 @@ async function simulateSettlePremiumFrom(params) {
|
|
|
26515
26706
|
} catch (error) {
|
|
26516
26707
|
const _meta = await metaPromise;
|
|
26517
26708
|
const errorMessage = error instanceof Error ? error.message : "Simulation failed";
|
|
26518
|
-
const
|
|
26519
|
-
if (
|
|
26520
|
-
|
|
26521
|
-
|
|
26522
|
-
|
|
26523
|
-
|
|
26524
|
-
|
|
26525
|
-
|
|
26709
|
+
const isNotExercisable = errorMessage.includes("NoLegsExercisable") || errorMessage.includes("NotALongLeg");
|
|
26710
|
+
if (isNotExercisable) {
|
|
26711
|
+
const data = {
|
|
26712
|
+
exerciseFee0: 0n,
|
|
26713
|
+
exerciseFee1: 0n,
|
|
26714
|
+
canExercise: false,
|
|
26715
|
+
reason: errorMessage.includes("NoLegsExercisable") ? "No legs are exercisable (not ITM)" : "Position does not have a long leg"
|
|
26716
|
+
};
|
|
26717
|
+
return {
|
|
26718
|
+
success: true,
|
|
26719
|
+
data,
|
|
26720
|
+
gasEstimate: 0n,
|
|
26721
|
+
tokenFlow: emptyTokenFlow,
|
|
26722
|
+
_meta
|
|
26723
|
+
};
|
|
26724
|
+
}
|
|
26526
26725
|
return {
|
|
26527
26726
|
success: false,
|
|
26528
26727
|
error: error instanceof PanopticError ? error : new PanopticError(errorMessage, error instanceof Error ? error : void 0),
|
|
@@ -26532,89 +26731,41 @@ async function simulateSettlePremiumFrom(params) {
|
|
|
26532
26731
|
}
|
|
26533
26732
|
|
|
26534
26733
|
//#endregion
|
|
26535
|
-
//#region src/panoptic/v2/simulations/
|
|
26734
|
+
//#region src/panoptic/v2/simulations/simulateLiquidate.ts
|
|
26536
26735
|
/**
|
|
26537
|
-
* Simulate
|
|
26538
|
-
*
|
|
26539
|
-
* Individual failures (insolvent buyer, stale list, …) are soft: the target
|
|
26540
|
-
* lands in the unsettleable partition instead of failing the batch. Only
|
|
26541
|
-
* unexpected errors reject.
|
|
26736
|
+
* Simulate a liquidation operation.
|
|
26542
26737
|
*
|
|
26543
26738
|
* @param params - Simulation parameters
|
|
26544
|
-
* @returns
|
|
26739
|
+
* @returns Simulation result with liquidation data or error
|
|
26545
26740
|
*/
|
|
26546
|
-
async function
|
|
26547
|
-
const { client, poolAddress, account, positionIdListFrom,
|
|
26741
|
+
async function simulateLiquidate(params) {
|
|
26742
|
+
const { client, poolAddress, account, liquidatee, positionIdListFrom, positionIdListTo, positionIdListToFinal, blockNumber } = params;
|
|
26548
26743
|
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
26549
26744
|
const metaPromise = getBlockMeta({
|
|
26550
26745
|
client,
|
|
26551
26746
|
blockNumber: targetBlockNumber
|
|
26552
26747
|
});
|
|
26553
|
-
const
|
|
26554
|
-
|
|
26555
|
-
|
|
26556
|
-
|
|
26557
|
-
|
|
26558
|
-
|
|
26559
|
-
|
|
26560
|
-
|
|
26561
|
-
|
|
26562
|
-
})));
|
|
26563
|
-
const results = [];
|
|
26564
|
-
const settleable = [];
|
|
26565
|
-
let unsettleableCount = 0;
|
|
26566
|
-
let premium0 = 0n;
|
|
26567
|
-
let premium1 = 0n;
|
|
26568
|
-
simulations.forEach((sim, i) => {
|
|
26569
|
-
const simulation = sim.success ? sim.data : {
|
|
26570
|
-
premium0: 0n,
|
|
26571
|
-
premium1: 0n,
|
|
26572
|
-
settled0: 0n,
|
|
26573
|
-
settled1: 0n,
|
|
26574
|
-
canSettle: false,
|
|
26575
|
-
reason: sim.error.message
|
|
26576
|
-
};
|
|
26577
|
-
results.push({
|
|
26578
|
-
target: targets[i],
|
|
26579
|
-
simulation
|
|
26580
|
-
});
|
|
26581
|
-
if (simulation.canSettle) {
|
|
26582
|
-
settleable.push(targets[i]);
|
|
26583
|
-
premium0 += simulation.premium0;
|
|
26584
|
-
premium1 += simulation.premium1;
|
|
26585
|
-
} else unsettleableCount += 1;
|
|
26586
|
-
});
|
|
26587
|
-
const _meta = await metaPromise;
|
|
26588
|
-
return {
|
|
26589
|
-
results,
|
|
26590
|
-
settleable,
|
|
26591
|
-
unsettleableCount,
|
|
26592
|
-
premium0,
|
|
26593
|
-
premium1,
|
|
26594
|
-
_meta
|
|
26748
|
+
const emptyTokenFlow = {
|
|
26749
|
+
delta0: 0n,
|
|
26750
|
+
delta1: 0n,
|
|
26751
|
+
balanceBefore0: 0n,
|
|
26752
|
+
balanceBefore1: 0n,
|
|
26753
|
+
balanceAfter0: 0n,
|
|
26754
|
+
balanceAfter1: 0n,
|
|
26755
|
+
tickBefore: null,
|
|
26756
|
+
tickAfter: null
|
|
26595
26757
|
};
|
|
26596
|
-
}
|
|
26597
|
-
/**
|
|
26598
|
-
* Simulate a full settle sequence (all settles + optional close) as the one
|
|
26599
|
-
* multicall that `executeSettleSequence` submits, measuring the caller's
|
|
26600
|
-
* total token flow and gas.
|
|
26601
|
-
*
|
|
26602
|
-
* @param params - Simulation parameters
|
|
26603
|
-
* @returns Simulation result with the caller's net flow, or error
|
|
26604
|
-
*/
|
|
26605
|
-
async function simulateSettleSequence(params) {
|
|
26606
|
-
const { client, poolAddress, account, blockNumber } = params;
|
|
26607
|
-
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
26608
|
-
const metaPromise = getBlockMeta({
|
|
26609
|
-
client,
|
|
26610
|
-
blockNumber: targetBlockNumber
|
|
26611
|
-
});
|
|
26612
26758
|
try {
|
|
26613
|
-
const calls = buildSettleSequenceCalls(params);
|
|
26614
26759
|
const callData = encodeFunctionData({
|
|
26615
26760
|
abi: panopticPoolV2Abi,
|
|
26616
|
-
functionName: "
|
|
26617
|
-
args: [
|
|
26761
|
+
functionName: "dispatchFrom",
|
|
26762
|
+
args: [
|
|
26763
|
+
positionIdListFrom,
|
|
26764
|
+
liquidatee,
|
|
26765
|
+
positionIdListTo,
|
|
26766
|
+
positionIdListToFinal,
|
|
26767
|
+
0n
|
|
26768
|
+
]
|
|
26618
26769
|
});
|
|
26619
26770
|
const flowResult = await simulateWithTokenFlow({
|
|
26620
26771
|
client,
|
|
@@ -26623,15 +26774,43 @@ async function simulateSettleSequence(params) {
|
|
|
26623
26774
|
callData,
|
|
26624
26775
|
blockNumber: targetBlockNumber
|
|
26625
26776
|
});
|
|
26626
|
-
if (!flowResult.success || !flowResult.tokenFlow)
|
|
26777
|
+
if (!flowResult.success || !flowResult.tokenFlow) {
|
|
26778
|
+
const errorMessage = flowResult.error || "Simulation failed";
|
|
26779
|
+
const isNotLiquidatable = errorMessage.includes("NotMarginCalled") || errorMessage.includes("AccountInsolvent");
|
|
26780
|
+
if (isNotLiquidatable) {
|
|
26781
|
+
const _meta$1 = await metaPromise;
|
|
26782
|
+
const data$1 = {
|
|
26783
|
+
bonus0: 0n,
|
|
26784
|
+
bonus1: 0n,
|
|
26785
|
+
positionsClosed: [],
|
|
26786
|
+
isLiquidatable: false,
|
|
26787
|
+
shortfall0: 0n,
|
|
26788
|
+
shortfall1: 0n
|
|
26789
|
+
};
|
|
26790
|
+
return {
|
|
26791
|
+
success: true,
|
|
26792
|
+
data: data$1,
|
|
26793
|
+
gasEstimate: 0n,
|
|
26794
|
+
tokenFlow: emptyTokenFlow,
|
|
26795
|
+
_meta: _meta$1
|
|
26796
|
+
};
|
|
26797
|
+
}
|
|
26798
|
+
throw new PanopticError(errorMessage);
|
|
26799
|
+
}
|
|
26627
26800
|
const _meta = await metaPromise;
|
|
26628
26801
|
const tokenFlow = flowResult.tokenFlow;
|
|
26802
|
+
const positionsClosed = positionIdListTo.filter((id) => !positionIdListToFinal.includes(id));
|
|
26803
|
+
const data = {
|
|
26804
|
+
bonus0: tokenFlow.delta0 > 0n ? tokenFlow.delta0 : 0n,
|
|
26805
|
+
bonus1: tokenFlow.delta1 > 0n ? tokenFlow.delta1 : 0n,
|
|
26806
|
+
positionsClosed,
|
|
26807
|
+
isLiquidatable: true,
|
|
26808
|
+
shortfall0: 0n,
|
|
26809
|
+
shortfall1: 0n
|
|
26810
|
+
};
|
|
26629
26811
|
return {
|
|
26630
26812
|
success: true,
|
|
26631
|
-
data
|
|
26632
|
-
delta0: tokenFlow.delta0,
|
|
26633
|
-
delta1: tokenFlow.delta1
|
|
26634
|
-
},
|
|
26813
|
+
data,
|
|
26635
26814
|
gasEstimate: flowResult.gasEstimate,
|
|
26636
26815
|
tokenFlow,
|
|
26637
26816
|
_meta
|
|
@@ -26639,6 +26818,24 @@ async function simulateSettleSequence(params) {
|
|
|
26639
26818
|
} catch (error) {
|
|
26640
26819
|
const _meta = await metaPromise;
|
|
26641
26820
|
const errorMessage = error instanceof Error ? error.message : "Simulation failed";
|
|
26821
|
+
const isNotLiquidatable = errorMessage.includes("NotMarginCalled") || errorMessage.includes("AccountInsolvent");
|
|
26822
|
+
if (isNotLiquidatable) {
|
|
26823
|
+
const data = {
|
|
26824
|
+
bonus0: 0n,
|
|
26825
|
+
bonus1: 0n,
|
|
26826
|
+
positionsClosed: [],
|
|
26827
|
+
isLiquidatable: false,
|
|
26828
|
+
shortfall0: 0n,
|
|
26829
|
+
shortfall1: 0n
|
|
26830
|
+
};
|
|
26831
|
+
return {
|
|
26832
|
+
success: true,
|
|
26833
|
+
data,
|
|
26834
|
+
gasEstimate: 0n,
|
|
26835
|
+
tokenFlow: emptyTokenFlow,
|
|
26836
|
+
_meta
|
|
26837
|
+
};
|
|
26838
|
+
}
|
|
26642
26839
|
return {
|
|
26643
26840
|
success: false,
|
|
26644
26841
|
error: error instanceof PanopticError ? error : new PanopticError(errorMessage, error instanceof Error ? error : void 0),
|
|
@@ -28652,6 +28849,441 @@ function createEventPoller(params) {
|
|
|
28652
28849
|
};
|
|
28653
28850
|
}
|
|
28654
28851
|
|
|
28852
|
+
//#endregion
|
|
28853
|
+
//#region src/panoptic/v2/strike/ladder.ts
|
|
28854
|
+
/** Target number of rungs across a leg's full range (lower tick → upper tick). */
|
|
28855
|
+
const STRIKE_LADDER_TARGET_STRIKES = 16n;
|
|
28856
|
+
/** Nice increment mantissas, in tenths (1, 2.5, 5) × 10ⁿ. */
|
|
28857
|
+
const NICE_MANTISSAS_TENTHS = [
|
|
28858
|
+
10n,
|
|
28859
|
+
25n,
|
|
28860
|
+
50n
|
|
28861
|
+
];
|
|
28862
|
+
/** Upper bound on rung hops when searching for a tick-changing step. */
|
|
28863
|
+
const MAX_STEP_ITERATIONS = 512;
|
|
28864
|
+
/** Decimal precision used when rendering exact tick prices as strings. */
|
|
28865
|
+
const PRICE_PRECISION = 30n;
|
|
28866
|
+
function floorDiv(a, b) {
|
|
28867
|
+
const q = a / b;
|
|
28868
|
+
return a % b !== 0n && a < 0n !== b < 0n ? q - 1n : q;
|
|
28869
|
+
}
|
|
28870
|
+
function floorMod(a, b) {
|
|
28871
|
+
return a - floorDiv(a, b) * b;
|
|
28872
|
+
}
|
|
28873
|
+
function ceilDiv(a, b) {
|
|
28874
|
+
return -floorDiv(-a, b);
|
|
28875
|
+
}
|
|
28876
|
+
/** round(a / b) to nearest, ties up. */
|
|
28877
|
+
function roundDiv(a, b) {
|
|
28878
|
+
return floorDiv(2n * a + b, 2n * b);
|
|
28879
|
+
}
|
|
28880
|
+
function pow10(exp) {
|
|
28881
|
+
let result = 1n;
|
|
28882
|
+
for (let i = 0n; i < exp; i++) result *= 10n;
|
|
28883
|
+
return result;
|
|
28884
|
+
}
|
|
28885
|
+
function gcd(a, b) {
|
|
28886
|
+
a = a < 0n ? -a : a;
|
|
28887
|
+
b = b < 0n ? -b : b;
|
|
28888
|
+
while (b !== 0n) [a, b] = [b, a % b];
|
|
28889
|
+
return a;
|
|
28890
|
+
}
|
|
28891
|
+
function reduce(f) {
|
|
28892
|
+
const g = gcd(f.numerator, f.denominator);
|
|
28893
|
+
return g <= 1n ? f : {
|
|
28894
|
+
numerator: f.numerator / g,
|
|
28895
|
+
denominator: f.denominator / g
|
|
28896
|
+
};
|
|
28897
|
+
}
|
|
28898
|
+
function fromBigint(n) {
|
|
28899
|
+
return {
|
|
28900
|
+
numerator: n,
|
|
28901
|
+
denominator: 1n
|
|
28902
|
+
};
|
|
28903
|
+
}
|
|
28904
|
+
function mul(a, b) {
|
|
28905
|
+
return reduce({
|
|
28906
|
+
numerator: a.numerator * b.numerator,
|
|
28907
|
+
denominator: a.denominator * b.denominator
|
|
28908
|
+
});
|
|
28909
|
+
}
|
|
28910
|
+
function add(a, b) {
|
|
28911
|
+
return reduce({
|
|
28912
|
+
numerator: a.numerator * b.denominator + b.numerator * a.denominator,
|
|
28913
|
+
denominator: a.denominator * b.denominator
|
|
28914
|
+
});
|
|
28915
|
+
}
|
|
28916
|
+
function sub(a, b) {
|
|
28917
|
+
return add(a, {
|
|
28918
|
+
numerator: -b.numerator,
|
|
28919
|
+
denominator: b.denominator
|
|
28920
|
+
});
|
|
28921
|
+
}
|
|
28922
|
+
/** -1 | 0 | 1 comparing a to b. */
|
|
28923
|
+
function cmp(a, b) {
|
|
28924
|
+
const l = a.numerator * b.denominator;
|
|
28925
|
+
const r = b.numerator * a.denominator;
|
|
28926
|
+
return l === r ? 0 : l < r ? -1 : 1;
|
|
28927
|
+
}
|
|
28928
|
+
const LADDER_MIN = fromBigint(1n);
|
|
28929
|
+
/** Largest normalised price on the ladder. Prices above are "outside". */
|
|
28930
|
+
const LADDER_MAX = fromBigint(1000000n);
|
|
28931
|
+
function parseDecimal(value) {
|
|
28932
|
+
const trimmed = value.trim();
|
|
28933
|
+
const [basePart, exponentPart] = trimmed.toLowerCase().split("e");
|
|
28934
|
+
const [integerStr, fractionalStr = ""] = basePart.split(".");
|
|
28935
|
+
let numerator = BigInt(`${integerStr === "" ? "0" : integerStr}${fractionalStr}`);
|
|
28936
|
+
let denominator = pow10(BigInt(fractionalStr.length));
|
|
28937
|
+
if (exponentPart !== void 0 && exponentPart !== "") {
|
|
28938
|
+
const exponent = BigInt(exponentPart);
|
|
28939
|
+
if (exponent > 0n) numerator *= pow10(exponent);
|
|
28940
|
+
else if (exponent < 0n) denominator *= pow10(-exponent);
|
|
28941
|
+
}
|
|
28942
|
+
if (numerator <= 0n) throw new Error("Price must be positive");
|
|
28943
|
+
return reduce({
|
|
28944
|
+
numerator,
|
|
28945
|
+
denominator
|
|
28946
|
+
});
|
|
28947
|
+
}
|
|
28948
|
+
/** Render a positive fraction as a decimal string with trailing zeros trimmed. */
|
|
28949
|
+
function fractionToDecimal(f, precision) {
|
|
28950
|
+
const scaled = f.numerator * pow10(precision) / f.denominator;
|
|
28951
|
+
const digits = scaled.toString().padStart(Number(precision) + 1, "0");
|
|
28952
|
+
const intPart = digits.slice(0, digits.length - Number(precision));
|
|
28953
|
+
const fracPart = digits.slice(digits.length - Number(precision)).replace(/0+$/, "");
|
|
28954
|
+
return fracPart.length === 0 ? intPart : `${intPart}.${fracPart}`;
|
|
28955
|
+
}
|
|
28956
|
+
/** 10^k as an exact fraction, k may be negative. */
|
|
28957
|
+
function powerOfTen(k) {
|
|
28958
|
+
return k >= 0n ? fromBigint(pow10(k)) : {
|
|
28959
|
+
numerator: 1n,
|
|
28960
|
+
denominator: pow10(-k)
|
|
28961
|
+
};
|
|
28962
|
+
}
|
|
28963
|
+
/** floor(log10(f)) for a positive fraction. */
|
|
28964
|
+
function floorLog10(f) {
|
|
28965
|
+
let e = BigInt(f.numerator.toString().length - f.denominator.toString().length);
|
|
28966
|
+
while (cmp(f, powerOfTen(e)) < 0) e -= 1n;
|
|
28967
|
+
while (cmp(f, powerOfTen(e + 1n)) >= 0) e += 1n;
|
|
28968
|
+
return e;
|
|
28969
|
+
}
|
|
28970
|
+
function orientTick(tick, orient) {
|
|
28971
|
+
return orient.asset === 0n ? tick : -tick;
|
|
28972
|
+
}
|
|
28973
|
+
/** Exact-enough price of `tick` in the caller's orientation. */
|
|
28974
|
+
function tickToOrientedPrice(tick, orient) {
|
|
28975
|
+
const price = tickToPriceDecimalScaled(orientTick(tick, orient), orient.assetDecimals, orient.quoteDecimals, PRICE_PRECISION);
|
|
28976
|
+
return parseDecimal(price);
|
|
28977
|
+
}
|
|
28978
|
+
/** Nearest integer tick for a caller-oriented decimal price. */
|
|
28979
|
+
function orientedPriceToTick(price, orient) {
|
|
28980
|
+
const t = priceToTick(price, orient.assetDecimals, orient.quoteDecimals);
|
|
28981
|
+
return orientTick(t, orient);
|
|
28982
|
+
}
|
|
28983
|
+
/**
|
|
28984
|
+
* Relative rung step for a leg: `1.0001^(round(width·tickSpacing / TARGET)) − 1`.
|
|
28985
|
+
* Rungs scale with price (they are multiples of a price-proportional increment), so
|
|
28986
|
+
* spacing them by the range's TARGET-th root yields ≈TARGET rungs across the range
|
|
28987
|
+
* regardless of how wide it is.
|
|
28988
|
+
*/
|
|
28989
|
+
function relativeStep(width, tickSpacing) {
|
|
28990
|
+
validateGeometry(width, tickSpacing);
|
|
28991
|
+
const ticks = roundDiv(width * tickSpacing, STRIKE_LADDER_TARGET_STRIKES);
|
|
28992
|
+
const ratio = parseDecimal(tickToPriceDecimalScaled(ticks < 1n ? 1n : ticks, 0n, 0n, PRICE_PRECISION));
|
|
28993
|
+
return sub(ratio, fromBigint(1n));
|
|
28994
|
+
}
|
|
28995
|
+
/** Nice increment `m × 10ⁿ` (m ∈ {1, 2.5, 5}) with the smallest log-distance to `raw`. */
|
|
28996
|
+
function niceIncrement(raw) {
|
|
28997
|
+
const e = floorLog10(raw);
|
|
28998
|
+
const scale = (tenths) => mul(fromBigint(tenths), powerOfTen(e - 1n));
|
|
28999
|
+
const candidates = [...NICE_MANTISSAS_TENTHS.map(scale), scale(100n)];
|
|
29000
|
+
let lo = candidates[0] ?? powerOfTen(e);
|
|
29001
|
+
for (const hi of candidates.slice(1)) {
|
|
29002
|
+
if (cmp(raw, hi) < 0) return cmp(mul(raw, raw), mul(lo, hi)) <= 0 ? lo : hi;
|
|
29003
|
+
lo = hi;
|
|
29004
|
+
}
|
|
29005
|
+
return lo;
|
|
29006
|
+
}
|
|
29007
|
+
/** Rung increment at normalised price `p` for the given relative step. */
|
|
29008
|
+
function incrementAt(p, rf) {
|
|
29009
|
+
return niceIncrement(mul(p, rf));
|
|
29010
|
+
}
|
|
29011
|
+
/** Normalise a price to `max(p, 1/p)` and remember whether it was inverted. */
|
|
29012
|
+
function normalise(price) {
|
|
29013
|
+
if (price.numerator >= price.denominator) return {
|
|
29014
|
+
value: price,
|
|
29015
|
+
reciprocal: false
|
|
29016
|
+
};
|
|
29017
|
+
return {
|
|
29018
|
+
value: {
|
|
29019
|
+
numerator: price.denominator,
|
|
29020
|
+
denominator: price.numerator
|
|
29021
|
+
},
|
|
29022
|
+
reciprocal: true
|
|
29023
|
+
};
|
|
29024
|
+
}
|
|
29025
|
+
/** Is `r` a multiple of `inc`? */
|
|
29026
|
+
function isMultiple(r, inc) {
|
|
29027
|
+
return r.numerator * inc.denominator % (r.denominator * inc.numerator) === 0n;
|
|
29028
|
+
}
|
|
29029
|
+
/** Smallest multiple of `inc` strictly greater than `x`. */
|
|
29030
|
+
function ceilMultipleStrict(x, inc) {
|
|
29031
|
+
const k = floorDiv(x.numerator * inc.denominator, x.denominator * inc.numerator) + 1n;
|
|
29032
|
+
return mul(fromBigint(k), inc);
|
|
29033
|
+
}
|
|
29034
|
+
/** Largest multiple of `inc` strictly smaller than `x`. */
|
|
29035
|
+
function floorMultipleStrict(x, inc) {
|
|
29036
|
+
const k = ceilDiv(x.numerator * inc.denominator, x.denominator * inc.numerator) - 1n;
|
|
29037
|
+
return mul(fromBigint(k), inc);
|
|
29038
|
+
}
|
|
29039
|
+
/**
|
|
29040
|
+
* The rung set is `{ r : r is a multiple of incrementAt(r) }`. Because the
|
|
29041
|
+
* increment grows with price, a multiple of a finer increment can land inside a
|
|
29042
|
+
* coarser band where it is no longer a rung; these helpers push such a candidate
|
|
29043
|
+
* up/down until it is a multiple of its own band's increment.
|
|
29044
|
+
*/
|
|
29045
|
+
function isRung(r, rf) {
|
|
29046
|
+
return r.numerator > 0n && isMultiple(r, incrementAt(r, rf));
|
|
29047
|
+
}
|
|
29048
|
+
function fixUp(c, rf) {
|
|
29049
|
+
for (let i = 0; i < 64 && !isRung(c, rf); i++) c = ceilMultipleStrict(c, incrementAt(c, rf));
|
|
29050
|
+
return c;
|
|
29051
|
+
}
|
|
29052
|
+
function fixDown(c, rf) {
|
|
29053
|
+
for (let i = 0; i < 64 && c.numerator > 0n && !isRung(c, rf); i++) c = floorMultipleStrict(c, incrementAt(c, rf));
|
|
29054
|
+
return c;
|
|
29055
|
+
}
|
|
29056
|
+
/** Smallest rung strictly above `x` (may exceed the ladder top). */
|
|
29057
|
+
function nextRungAbove(x, rf) {
|
|
29058
|
+
const incHere = incrementAt(x, rf);
|
|
29059
|
+
const incs = [incHere, incrementAt(add(x, incHere), rf)];
|
|
29060
|
+
let best = null;
|
|
29061
|
+
for (const inc of incs) {
|
|
29062
|
+
const c = fixUp(ceilMultipleStrict(x, inc), rf);
|
|
29063
|
+
if (cmp(c, x) > 0 && (best === null || cmp(c, best) < 0)) best = c;
|
|
29064
|
+
}
|
|
29065
|
+
if (best === null) throw new PanopticValidationError("No ladder rung above price");
|
|
29066
|
+
return best;
|
|
29067
|
+
}
|
|
29068
|
+
/** Largest rung strictly below `x` (may fall below the ladder floor). */
|
|
29069
|
+
function prevRungBelow(x, rf) {
|
|
29070
|
+
const incHere = incrementAt(x, rf);
|
|
29071
|
+
const finer = incrementAt(sub(x, incHere), rf);
|
|
29072
|
+
let best = null;
|
|
29073
|
+
for (const inc of [incHere, finer]) {
|
|
29074
|
+
const c = fixDown(floorMultipleStrict(x, inc), rf);
|
|
29075
|
+
if (c.numerator > 0n && cmp(c, x) < 0 && (best === null || cmp(c, best) > 0)) best = c;
|
|
29076
|
+
}
|
|
29077
|
+
return best ?? fromBigint(0n);
|
|
29078
|
+
}
|
|
29079
|
+
/** Nearest rung price to a normalised price, or null when above the ladder. */
|
|
29080
|
+
function nearestRungPrice(normalised, rf) {
|
|
29081
|
+
let rung;
|
|
29082
|
+
if (isRung(normalised, rf)) rung = normalised;
|
|
29083
|
+
else {
|
|
29084
|
+
const up = nextRungAbove(normalised, rf);
|
|
29085
|
+
const down = prevRungBelow(normalised, rf);
|
|
29086
|
+
if (down.numerator <= 0n) rung = up;
|
|
29087
|
+
else rung = cmp(sub(normalised, down), sub(up, normalised)) <= 0 ? down : up;
|
|
29088
|
+
}
|
|
29089
|
+
if (cmp(rung, LADDER_MIN) < 0) rung = LADDER_MIN;
|
|
29090
|
+
if (cmp(rung, LADDER_MAX) > 0) return null;
|
|
29091
|
+
return rung;
|
|
29092
|
+
}
|
|
29093
|
+
/** Step one rung up (+1) or down (-1) on the normalised ladder. Null when leaving it. */
|
|
29094
|
+
function stepRungPrice(rung, direction, rf) {
|
|
29095
|
+
const next = direction > 0n ? nextRungAbove(rung, rf) : prevRungBelow(rung, rf);
|
|
29096
|
+
if (cmp(next, LADDER_MIN) < 0 || cmp(next, LADDER_MAX) > 0) return null;
|
|
29097
|
+
return next;
|
|
29098
|
+
}
|
|
29099
|
+
/** Nominal caller-oriented price of a rung as an exact fraction. */
|
|
29100
|
+
function rungToPrice(rung) {
|
|
29101
|
+
return rung.reciprocal ? {
|
|
29102
|
+
numerator: rung.price.denominator,
|
|
29103
|
+
denominator: rung.price.numerator
|
|
29104
|
+
} : rung.price;
|
|
29105
|
+
}
|
|
29106
|
+
function rungToPriceString(rung) {
|
|
29107
|
+
return fractionToDecimal(rungToPrice(rung), PRICE_PRECISION);
|
|
29108
|
+
}
|
|
29109
|
+
function nearestRung(price, rf) {
|
|
29110
|
+
const { value, reciprocal } = normalise(price);
|
|
29111
|
+
const p = nearestRungPrice(value, rf);
|
|
29112
|
+
return p === null ? null : {
|
|
29113
|
+
price: p,
|
|
29114
|
+
reciprocal
|
|
29115
|
+
};
|
|
29116
|
+
}
|
|
29117
|
+
/**
|
|
29118
|
+
* Step a rung in the caller's price direction. For reciprocal quotes a higher
|
|
29119
|
+
* caller price is a lower normalised price, so the direction flips.
|
|
29120
|
+
*/
|
|
29121
|
+
function stepRung(rung, direction, rf) {
|
|
29122
|
+
const normalisedDir = rung.reciprocal ? direction > 0n ? -1n : 1n : direction;
|
|
29123
|
+
const p = stepRungPrice(rung.price, normalisedDir, rf);
|
|
29124
|
+
return p === null ? null : {
|
|
29125
|
+
price: p,
|
|
29126
|
+
reciprocal: rung.reciprocal
|
|
29127
|
+
};
|
|
29128
|
+
}
|
|
29129
|
+
/** Reject geometry the ladder cannot place: non-positive inputs or a span wider than the tick domain. */
|
|
29130
|
+
function validateGeometry(width, tickSpacing) {
|
|
29131
|
+
if (width <= 0n) throw new PanopticValidationError("width must be positive");
|
|
29132
|
+
if (tickSpacing <= 0n) throw new PanopticValidationError("tickSpacing must be positive");
|
|
29133
|
+
if (width * tickSpacing > MAX_TICK - MIN_TICK) throw new PanopticValidationError("width * tickSpacing exceeds the tick domain");
|
|
29134
|
+
}
|
|
29135
|
+
/** `rangeDown`/`rangeUp` exactly as `PanopticMath.getRangesFromStrike`. */
|
|
29136
|
+
function rangesFromStrike(width, tickSpacing) {
|
|
29137
|
+
const span = width * tickSpacing;
|
|
29138
|
+
return {
|
|
29139
|
+
rangeDown: span / 2n,
|
|
29140
|
+
rangeUp: ceilDiv(span, 2n)
|
|
29141
|
+
};
|
|
29142
|
+
}
|
|
29143
|
+
/**
|
|
29144
|
+
* Nearest valid strike tick to `exactTick` for `width`/`tickSpacing`.
|
|
29145
|
+
* Valid strikes satisfy `strike ≡ rangeDown (mod tickSpacing)`; the result is
|
|
29146
|
+
* shifted in whole tick spacings so the leg's ticks stay within `[MIN_TICK, MAX_TICK]`.
|
|
29147
|
+
*/
|
|
29148
|
+
function canonicalStrikeForWidth(exactTick, width, tickSpacing) {
|
|
29149
|
+
validateGeometry(width, tickSpacing);
|
|
29150
|
+
const { rangeDown, rangeUp } = rangesFromStrike(width, tickSpacing);
|
|
29151
|
+
const offset = floorMod(rangeDown, tickSpacing);
|
|
29152
|
+
let strike = roundDiv(exactTick - offset, tickSpacing) * tickSpacing + offset;
|
|
29153
|
+
while (strike - rangeDown < MIN_TICK) strike += tickSpacing;
|
|
29154
|
+
while (strike + rangeUp > MAX_TICK) strike -= tickSpacing;
|
|
29155
|
+
return strike;
|
|
29156
|
+
}
|
|
29157
|
+
function rungToStrike(rung, geom) {
|
|
29158
|
+
const nominalPrice = rungToPriceString(rung);
|
|
29159
|
+
const exactTick = orientedPriceToTick(nominalPrice, geom.orient);
|
|
29160
|
+
return {
|
|
29161
|
+
tick: canonicalStrikeForWidth(exactTick, geom.width, geom.tickSpacing),
|
|
29162
|
+
nominalPrice
|
|
29163
|
+
};
|
|
29164
|
+
}
|
|
29165
|
+
function classifyTick(tick, geom, rf) {
|
|
29166
|
+
const rung = nearestRung(tickToOrientedPrice(tick, geom.orient), rf);
|
|
29167
|
+
if (rung === null) return { kind: "outside-ladder" };
|
|
29168
|
+
const canonical = rungToStrike(rung, geom);
|
|
29169
|
+
return canonical.tick === tick ? {
|
|
29170
|
+
kind: "ladder",
|
|
29171
|
+
nominalPrice: canonical.nominalPrice
|
|
29172
|
+
} : { kind: "off-ladder" };
|
|
29173
|
+
}
|
|
29174
|
+
/**
|
|
29175
|
+
* A rung's canonical tick is only usable when that tick classifies back to the
|
|
29176
|
+
* same rung (`classifyStrike` → 'ladder'). When rungs are finer than the tick
|
|
29177
|
+
* grid two rungs can share a tick and only one of them "owns" it; return the
|
|
29178
|
+
* owner's strike, or null when this rung does not own its tick.
|
|
29179
|
+
*/
|
|
29180
|
+
function ownedStrike(rung, geom, rf) {
|
|
29181
|
+
const strike = rungToStrike(rung, geom);
|
|
29182
|
+
const cls = classifyTick(strike.tick, geom, rf);
|
|
29183
|
+
return cls.kind === "ladder" ? {
|
|
29184
|
+
tick: strike.tick,
|
|
29185
|
+
nominalPrice: cls.nominalPrice
|
|
29186
|
+
} : null;
|
|
29187
|
+
}
|
|
29188
|
+
/**
|
|
29189
|
+
* Classify a strike tick against the ladder for its width.
|
|
29190
|
+
*
|
|
29191
|
+
* - `ladder`: the tick is the canonical tick of its nearest rung → show `nominalPrice`.
|
|
29192
|
+
* - `off-ladder`: an in-range tick that is not a rung's canonical tick (e.g. real AMM
|
|
29193
|
+
* liquidity at an arbitrary strike) → show the exact price.
|
|
29194
|
+
* - `outside-ladder`: the normalised price exceeds 1,000,000 → legacy behaviour.
|
|
29195
|
+
*/
|
|
29196
|
+
function classifyStrike(params) {
|
|
29197
|
+
return classifyTick(params.tick, params, relativeStep(params.width, params.tickSpacing));
|
|
29198
|
+
}
|
|
29199
|
+
/**
|
|
29200
|
+
* Resolve a tick to a ladder strike.
|
|
29201
|
+
*
|
|
29202
|
+
* - `step` 0 (default): the ladder tick nearest to `tick` (the tick's own rung when
|
|
29203
|
+
* it owns one, otherwise the closest owned neighbour).
|
|
29204
|
+
* - `step` ±1: the nearest ladder tick strictly beyond `tick` in that price direction
|
|
29205
|
+
* (rungs finer than the tick grid can collapse onto one tick, so a single rung hop
|
|
29206
|
+
* may not move the strike).
|
|
29207
|
+
*
|
|
29208
|
+
* Returns null when the target lies outside the ladder (normalised price > 1e6).
|
|
29209
|
+
*/
|
|
29210
|
+
function resolveLadderStrike(params) {
|
|
29211
|
+
const step = params.step ?? 0n;
|
|
29212
|
+
const rf = relativeStep(params.width, params.tickSpacing);
|
|
29213
|
+
const start = nearestRung(tickToOrientedPrice(params.tick, params.orient), rf);
|
|
29214
|
+
if (start === null) return null;
|
|
29215
|
+
const startOriented = orientTick(params.tick, params.orient);
|
|
29216
|
+
if (step === 0n) {
|
|
29217
|
+
const own = ownedStrike(start, params, rf);
|
|
29218
|
+
if (own !== null) return own;
|
|
29219
|
+
let lo = start;
|
|
29220
|
+
let hi = start;
|
|
29221
|
+
for (let i = 0; i < MAX_STEP_ITERATIONS; i++) {
|
|
29222
|
+
lo = lo === null ? null : stepRung(lo, -1n, rf);
|
|
29223
|
+
hi = hi === null ? null : stepRung(hi, 1n, rf);
|
|
29224
|
+
const a = lo === null ? null : ownedStrike(lo, params, rf);
|
|
29225
|
+
const b = hi === null ? null : ownedStrike(hi, params, rf);
|
|
29226
|
+
if (a !== null && b !== null) {
|
|
29227
|
+
const da = startOriented - orientTick(a.tick, params.orient);
|
|
29228
|
+
const db = orientTick(b.tick, params.orient) - startOriented;
|
|
29229
|
+
return da <= db ? a : b;
|
|
29230
|
+
}
|
|
29231
|
+
if (a !== null) return a;
|
|
29232
|
+
if (b !== null) return b;
|
|
29233
|
+
if (lo === null && hi === null) return null;
|
|
29234
|
+
}
|
|
29235
|
+
return null;
|
|
29236
|
+
}
|
|
29237
|
+
let rung = start;
|
|
29238
|
+
for (let i = 0; i < MAX_STEP_ITERATIONS && rung !== null; i++) {
|
|
29239
|
+
const own = ownedStrike(rung, params, rf);
|
|
29240
|
+
if (own !== null) {
|
|
29241
|
+
const oriented = orientTick(own.tick, params.orient);
|
|
29242
|
+
if (step > 0n ? oriented > startOriented : oriented < startOriented) return own;
|
|
29243
|
+
}
|
|
29244
|
+
rung = stepRung(rung, step, rf);
|
|
29245
|
+
}
|
|
29246
|
+
return null;
|
|
29247
|
+
}
|
|
29248
|
+
/**
|
|
29249
|
+
* Generate up to `count` ladder strikes centred on `centerTick`, sorted by
|
|
29250
|
+
* ascending caller price and deduplicated by tick. Rungs beyond the ladder are
|
|
29251
|
+
* omitted (the result may be shorter than `count`). Returns null when the
|
|
29252
|
+
* centre itself lies outside the ladder and `[]` when `count` is 0.
|
|
29253
|
+
*/
|
|
29254
|
+
function ladderStrikeSequence(params) {
|
|
29255
|
+
const rf = relativeStep(params.width, params.tickSpacing);
|
|
29256
|
+
if (params.count <= 0) return [];
|
|
29257
|
+
const center = nearestRung(tickToOrientedPrice(params.centerTick, params.orient), rf);
|
|
29258
|
+
if (center === null) return null;
|
|
29259
|
+
const half = Math.floor(params.count / 2);
|
|
29260
|
+
const below = [];
|
|
29261
|
+
const above = [];
|
|
29262
|
+
let r = center;
|
|
29263
|
+
for (let i = 0; i < half && r !== null; i++) {
|
|
29264
|
+
r = stepRung(r, -1n, rf);
|
|
29265
|
+
if (r !== null) below.push(r);
|
|
29266
|
+
}
|
|
29267
|
+
r = center;
|
|
29268
|
+
for (let i = 0; i < params.count - half - 1 && r !== null; i++) {
|
|
29269
|
+
r = stepRung(r, 1n, rf);
|
|
29270
|
+
if (r !== null) above.push(r);
|
|
29271
|
+
}
|
|
29272
|
+
const seen = new Set();
|
|
29273
|
+
const out = [];
|
|
29274
|
+
for (const rung of [
|
|
29275
|
+
...below.reverse(),
|
|
29276
|
+
center,
|
|
29277
|
+
...above
|
|
29278
|
+
]) {
|
|
29279
|
+
const strike = ownedStrike(rung, params, rf);
|
|
29280
|
+
if (strike === null || seen.has(strike.tick)) continue;
|
|
29281
|
+
seen.add(strike.tick);
|
|
29282
|
+
out.push(strike);
|
|
29283
|
+
}
|
|
29284
|
+
return out;
|
|
29285
|
+
}
|
|
29286
|
+
|
|
28655
29287
|
//#endregion
|
|
28656
29288
|
//#region src/panoptic/v2/bot/index.ts
|
|
28657
29289
|
/**
|
|
@@ -29186,5 +29818,5 @@ const VAULT_DISPLAY_NAME_RESOLVERS_PER_CHAIN = {
|
|
|
29186
29818
|
};
|
|
29187
29819
|
|
|
29188
29820
|
//#endregion
|
|
29189
|
-
export { AccountInsolventError, AlreadyInitializedError, BORROW_INDEX_BITS, BPS_DENOMINATOR, BPS_SCALE, BatchValidationError, BelowMinimumRedemptionError, CastingError, ChunkHasZeroLiquidityError, ChunkLimitError, CrossPoolError, DEFAULT_MAX_SPREAD, DEFAULT_MINT_BUFFER, DEFAULT_MIN_SWAP_RATIO_BPS, DEFAULT_RECONNECT_CONFIG, DEFAULT_VEGOID, DepositTooLargeError, DuplicateTokenIdError, EffectiveLiquidityAboveThresholdError, ExceedsMaximumRedemptionError, InputListFailError, InsufficientCreditLiquidityError, InvalidBuilderCodeError, InvalidHistoryRangeError, InvalidTickBoundError, InvalidTickError, InvalidTokenIdParameterError, InvalidUniswapCallbackError, LEG_BITS, LEG_LIMITS, LEG_MASKS, LengthMismatchError, LiquidityTooHighError, LoanSlotExhaustedError, MARKET_EPOCH_BITS, MARKET_EPOCH_SHIFT, MAX_TICK, MAX_TRACKED_CHUNKS, MINT_BUFFER, MINT_BUFFER_DENOMINATOR, MIN_TICK, MaxRetriesExceededError, MissingPositionIdsError, NO_LOWER_LIQUIDATION_TICK, NO_UPPER_LIQUIDATION_TICK, NetLiquidityZeroError, NetworkMismatchError, NoLegsExercisableError, NotALongLegError, NotBuilderError, NotEnoughLiquidityInChunkError, NotEnoughTokensError, NotGuardianError, NotMarginCalledError, NotPanopticPoolError, ORACLE_EPOCH_SECONDS, OracleRateLimitedError, PanopticError, PanopticHelperNotDeployedError, PanopticValidationError, PoolNotInitializedError, PositionCountNotZeroError, PositionNotOwnedError, PositionSnapshotNotFoundError, PositionTooLargeError, PriceBoundFailError, PriceImpactTooLargeError, ProviderLagError, RATE_AT_TARGET_BITS, REORG_DEPTH, REQUIRED_BASE_ERROR_SENTINEL, ReentrancyError, RpcError, RpcResponseError, SCHEMA_VERSION, SECONDS_PER_YEAR, STANDARD_TICK_WIDTHS, STORAGE_PREFIX, SafeModeError, StaleDataError, StaleOracleError, SwapTokenMismatchError, SyncTimeoutError, TOKEN_ID_BITS, TokenIdHasZeroLegsError, TooManyLegsOpenError, TransferFailedError, UNREALIZED_INTEREST_BITS, UTILIZATION_DENOMINATOR, UnauthorizedUniswapCallbackError, UnderOverFlowError, UnhealthyPoolError, WAD, WrongPoolIdError, WrongUniswapPoolError, ZERO_COLLATERAL, ZERO_VALUATION, ZeroAddressError, ZeroCollateralRequirementError, addLegToTokenId, addPendingPosition, addTrackedChunks, annualizePerSecondRateWad, applyMintBuffer, applyMintBufferPerToken, apportion, approve, approveAndWait, approvePool, assertCanBurn, assertCanForceExercise, assertCanLiquidate, assertCanMint, assertFresh, assertHealthy, assertTradeable, borrow, borrowAndWait, buildBatchDispatchArgs, buildCreditSwapCall, buildCreditWrappedDispatch, buildOpenPositionCalldata, buildSettleSequenceCalls, buildSfpmSwapCalldata, buildSfpmSwapPlan, buildTemporaryLoanRecoveryDispatch, buildTokenShortfallRecoveryDispatch, buildUniqueCredit, buildUniqueLoan, buildUniqueWidthZeroLeg, calculateAccountGreeksPure, calculatePortfolioDelta, calculatePortfolioGamma, calculatePortfolioGreeks, calculatePortfolioValue, calculatePositionDelta, calculatePositionDeltaDebtOnly, calculatePositionDeltaWithSwap, calculatePositionGamma, calculatePositionGreeks, calculatePositionValue, calculateResyncBlock, calculateSpreadWad, cancelTransaction, checkApproval, checkCollateralAcrossTicks, classifyStrategyGroups, cleanupStalePendingPositions, clearCheckpoint, clearPendingPositions, clearTrackedChunks, clearTrackedPositions, clearTradeHistory, closePosition, closePositionAndWait, collateralRuleKindFor, collateralTrackerV2Abi, computeV4PoolId, confirmPendingPosition, convertToAssets, convertToShares, countLegs, createEventPoller, createEventSubscription, createFileStorage, createFlowNeutralTokenId, createMemoryStorage, createNonceManager, createPoolFormatters, createTokenIdBuilder, decodeAllDispatchCalldata, decodeAllLegs, decodeDispatchCalldata, decodeLeftRightSigned, decodeLeftRightUnsigned, decodeLeg, decodeOraclePack, decodeOracleRiskParameters, decodeOracleTiming, decodePanopticTokenURI, decodePoolId, decodeTickSpacing, decodeTokenId, decodeVegoid, deployNewPool, deployNewPoolAndWait, deposit, depositAndWait, deriveSupplyRatePerSecWad, deriveUniqueTokenId, detectReorg, diagnoseOracleSafeMode, dispatch, dispatchAndWait, encodeLeg, encodePoolId, encodePoolKeyBytes, encodeV3PoolKeyBytes, encodeV4PoolId, ensureSfpmV3PoolInitialized, estimateBlockNumbers, estimateCollateralBreakdown, estimateCollateralRequired, executeBatchDispatch, executeBatchDispatchAndWait, executeSettleSequence, executeSettleSequenceAndWait, failPendingPosition, feesFromFeeGrowthDelta, fetchPoolId, fetchSfpmV3PoolId, forceExercise, forceExerciseAndWait, formatBlockNumber, formatBps, formatCompact, formatDatetime, formatDuration, formatDurationSeconds, formatFeeTier, formatGas, formatGwei, formatPerSecondRateWadAsAprPct, formatPerSecondRateWadAsApyPct, formatPoolIdHex, formatPriceRange, formatRateWad, formatRatioPercent, formatTick, formatTickRange, formatTimestamp, formatTimestampLocale, formatTokenAmount, formatTokenAmountSigned, formatTokenDelta, formatTokenFlow, formatTokenIdHex, formatTokenIdShort, formatTxHash, formatUtilization, formatWad, formatWadPercent, formatWadSigned, formatWei, generateOverlappingTokenIds, getAccountBuyingPower, getAccountCollateral, getAccountGreeks, getAccountHistory, getAccountPremia, getAccountSummaryBasic, getAccountSummaryRisk, getAssetIndex, getBlockMeta, getChainDeployment, getChunkLiquidities, getChunkSpreads, getClosedPositions, getClosedPositionsKey, getCollateralAddresses, getCollateralData, getCollateralSharePrices, getCollateralTotalAssetsBatch, getCurrentRates, getDeltaHedgeParams, getEnforcedTickLimits, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getForfeitablePremium, getGuardianUnlockState, getInterestState, getIrmCurrent, getIrmCurve, getItmAmounts, getLegDelta, getLegDeltaInVaultFrame, getLegGamma, getLegNetValueWidth0, getLegValue, getLiquidationPrices, getMarginBuffer, getMaxPositionSize, getMaxRedeem, getMaxWithdrawable, getNativeTokenPrice, getNetLiquidationValue, getNetLiquidationValues, getNotEnoughTokensError, getOpenPositionIds, getOpenPositionPreview, getOracleRiskParameters, getOracleState, getPanopticPoolAddress, getPanopticPoolFromPoolId, getPendingPositions, getPendingPositionsKey, getPool, getPoolDeploymentBlock, getPoolDisplayId, getPoolLiquidities, getPoolMetaKey, getPoolMetadata, getPoolPrefix, getPortfolioValue, getPosition, getPositionChunkData, getPositionEnrichmentData, getPositionGreeks, getPositionMetaKey, getPositions, getPositionsKey, getPositionsWithPremia, getPriceHistory, getPricesAtTick, getRealizedPnL, getRequiredCreditForITM, getRiskParameters, getSafeMode, getSchemaVersionKey, getStreamiaHistory, getSyncCheckpointKey, getSyncStatus, getTickSpacing, getTokenListId, getTrackedChunks, getTrackedChunksKey, getTrackedPositionIds, getTradeHistory, getUniswapFeeHistory, getUniswapV3LpPositionState, getUniswapV3PoolFromId, getUniswapV3PoolInfo, getUniswapV3PoolLiquidities, getUniswapV4LpPositionState, getUniswapV4PoolBasicState, getUniswapV4PoolInfo, getUniswapV4PoolKeyFromId, getUniswapV4PoolLiquidities, getUtilization, hasLoanOrCredit, hasLongLeg, interpolateBlocks, isCall, isCredit, isCreditLeg, isDefinedRisk, isGasError, isInputListFailError, isLiquidatable, isLoan, isLoanLeg, isNonceError, isPanopticErrorType, isPositionTracked, isRetryableRpcError, isShortOnly, isSpread, isSupportedChain, isolateGroupTokenId, jsonSerializer, liquidate, liquidateAndWait, loadCheckpoint, minePoolAddress, mint, mintAndWait, mintableAfterBuffer, multicallRead, openPosition, openPositionAndWait, optimizeTokenIdRiskPartners, oracleEpochAt, orderListForSettle, packMarketState, panopticPoolV2Abi, parseBps, parseCollateralLog, parsePanopticError, parsePoolLog, parseTokenAmount, parseTokenListId, parseWad, planDeriveStrategy, pokeOracle, pokeOracleAndWait, previewBorrow, previewDeposit, previewMint, previewRedeem, previewUnwrap, previewWithdraw, previewWrap, priceToTick, publicBroadcaster, quoteOneTokenFlow, quoteSfpmSwap, quoteTemporaryLoanRecovery, quoteTokenShortfallRecovery, quoteV3ExactIn, ratePerSecWadToAprPct, reconstructFromEvents, recoverSnapshot, recoverSnapshotFromTx, redeem, redeemAndWait, removeTrackedChunks, repay, repayAndWait, requireChainDeployment, resolveBlockNumbers, resolvePanopticPoolFromPoolId, resolveTokenIndex, resolveUniswapV4PoolKey, riskEngineAbi, rollPosition, rollPositionAndWait, roundToTickSpacing, saveCheckpoint, saveClosedPosition, scanChunks, selectDispatchForAccount, settleAccumulatedPremia, settleAccumulatedPremiaAndWait, settlePremiumFrom, settlePremiumFromAndWait, simulateBatchDispatch, simulateClosePosition, simulateDeployNewPool, simulateDeposit, simulateDispatch, simulateForceExercise, simulateLiquidate, simulateOpenPosition, simulateSFPMBurn, simulateSFPMMint, simulateSettle, simulateSettlePremiumBatch, simulateSettlePremiumFrom, simulateSettleSequence, simulateSwapExactIn, simulateSwapExactOut, simulateWithTokenFlow, simulateWithdraw, slippageBpsToTickDistance, smartRepay, smartRepayAndWait, speedUpTransaction, splitTokenIdByTimescale, sqrtPriceX96ToPriceDecimalScaled, sqrtPriceX96ToTick, supply, supplyAndWait, swapExactIn, swapExactInAndWait, swapExactOut, swapExactOutAndWait, syncPositions, tickLimits, tickToPrice, tickToPriceDecimalScaled, tickToSqrtPriceX96, toVaultFrameAtTick, truncateAddress, unsupply, unsupplyAndWait, unwrapWeth, unwrapWethAndWait, unwrapXstock, unwrapXstockAndWait, utilizationBpsToWad, utilizationPctToWad, validateBatch, validateBuilderCode, validatePoolId, verifyBlockContinuity, watchEvents, wethWrapAbi, withdraw, withdrawAndWait, withdrawWithPositions, withdrawWithPositionsAndWait, wrapEth, wrapEthAndWait, wrapXstock, wrapXstockAndWait, xstockWrapperAbi };
|
|
29821
|
+
export { AccountInsolventError, AlreadyInitializedError, BORROW_INDEX_BITS, BPS_DENOMINATOR, BPS_SCALE, BatchValidationError, BelowMinimumRedemptionError, CastingError, ChunkHasZeroLiquidityError, ChunkLimitError, CrossPoolError, DEFAULT_MAX_SPREAD, DEFAULT_MINT_BUFFER, DEFAULT_MIN_SWAP_RATIO_BPS, DEFAULT_RECONNECT_CONFIG, DEFAULT_VEGOID, DepositTooLargeError, DuplicateTokenIdError, EffectiveLiquidityAboveThresholdError, ExceedsMaximumRedemptionError, InputListFailError, InsufficientCreditLiquidityError, InvalidBuilderCodeError, InvalidHistoryRangeError, InvalidTickBoundError, InvalidTickError, InvalidTokenIdParameterError, InvalidUniswapCallbackError, LEG_BITS, LEG_LIMITS, LEG_MASKS, LengthMismatchError, LiquidityTooHighError, LoanSlotExhaustedError, MARKET_EPOCH_BITS, MARKET_EPOCH_SHIFT, MAX_TICK, MAX_TRACKED_CHUNKS, MINT_BUFFER, MINT_BUFFER_DENOMINATOR, MIN_TICK, MaxRetriesExceededError, MissingPositionIdsError, NO_LOWER_LIQUIDATION_TICK, NO_UPPER_LIQUIDATION_TICK, NetLiquidityZeroError, NetworkMismatchError, NoLegsExercisableError, NotALongLegError, NotBuilderError, NotEnoughLiquidityInChunkError, NotEnoughTokensError, NotGuardianError, NotMarginCalledError, NotPanopticPoolError, ORACLE_EPOCH_SECONDS, OracleRateLimitedError, PanopticError, PanopticHelperNotDeployedError, PanopticValidationError, PoolNotInitializedError, PositionCountNotZeroError, PositionNotOwnedError, PositionSnapshotNotFoundError, PositionTooLargeError, PriceBoundFailError, PriceImpactTooLargeError, ProviderLagError, RATE_AT_TARGET_BITS, REORG_DEPTH, REQUIRED_BASE_ERROR_SENTINEL, ReentrancyError, RpcError, RpcResponseError, SCHEMA_VERSION, SECONDS_PER_YEAR, STANDARD_TICK_WIDTHS, STORAGE_PREFIX, STRIKE_LADDER_TARGET_STRIKES, SafeModeError, StaleDataError, StaleOracleError, SwapTokenMismatchError, SyncTimeoutError, TOKEN_ID_BITS, TokenIdHasZeroLegsError, TooManyLegsOpenError, TransferFailedError, UNREALIZED_INTEREST_BITS, UTILIZATION_DENOMINATOR, UnauthorizedUniswapCallbackError, UnderOverFlowError, UnhealthyPoolError, UnsafePremiumSettlementError, WAD, WrongPoolIdError, WrongUniswapPoolError, ZERO_COLLATERAL, ZERO_VALUATION, ZeroAddressError, ZeroCollateralRequirementError, addLegToTokenId, addPendingPosition, addTrackedChunks, annualizePerSecondRateWad, applyMintBuffer, applyMintBufferPerToken, apportion, approve, approveAndWait, approvePool, assertCanBurn, assertCanForceExercise, assertCanLiquidate, assertCanMint, assertFresh, assertHealthy, assertTradeable, borrow, borrowAndWait, buildBatchDispatchArgs, buildCreditSwapCall, buildCreditWrappedDispatch, buildOpenPositionCalldata, buildProtectedSettleDispatch, buildProtectedSettlePlan, buildSettleSequenceCalls, buildSfpmSwapCalldata, buildSfpmSwapPlan, buildTemporaryLoanRecoveryDispatch, buildTokenShortfallRecoveryDispatch, buildUniqueCredit, buildUniqueLoan, buildUniqueWidthZeroLeg, calculateAccountGreeksPure, calculatePortfolioDelta, calculatePortfolioGamma, calculatePortfolioGreeks, calculatePortfolioValue, calculatePositionDelta, calculatePositionDeltaDebtOnly, calculatePositionDeltaWithSwap, calculatePositionGamma, calculatePositionGreeks, calculatePositionValue, calculateResyncBlock, calculateSpreadWad, cancelTransaction, checkApproval, checkCollateralAcrossTicks, classifyStrategyGroups, classifyStrike, cleanupStalePendingPositions, clearCheckpoint, clearPendingPositions, clearTrackedChunks, clearTrackedPositions, clearTradeHistory, closePosition, closePositionAndWait, collateralRuleKindFor, collateralTrackerV2Abi, computeV4PoolId, confirmPendingPosition, convertToAssets, convertToShares, countLegs, createEventPoller, createEventSubscription, createFileStorage, createFlowNeutralTokenId, createMemoryStorage, createNonceManager, createPoolFormatters, createTokenIdBuilder, decodeAllDispatchCalldata, decodeAllLegs, decodeDispatchCalldata, decodeLeftRightSigned, decodeLeftRightUnsigned, decodeLeg, decodeOraclePack, decodeOracleRiskParameters, decodeOracleTiming, decodePanopticTokenURI, decodePoolId, decodeTickSpacing, decodeTokenId, decodeVegoid, deployNewPool, deployNewPoolAndWait, deposit, depositAndWait, deriveSupplyRatePerSecWad, deriveUniqueTokenId, detectReorg, diagnoseOracleSafeMode, dispatch, dispatchAndWait, encodeLeg, encodePoolId, encodePoolKeyBytes, encodeV3PoolKeyBytes, encodeV4PoolId, ensureSfpmV3PoolInitialized, estimateBlockNumbers, estimateCollateralBreakdown, estimateCollateralRequired, executeBatchDispatch, executeBatchDispatchAndWait, executeSettleSequence, executeSettleSequenceAndWait, failPendingPosition, feesFromFeeGrowthDelta, fetchPoolId, fetchSfpmV3PoolId, forceExercise, forceExerciseAndWait, formatBlockNumber, formatBps, formatCompact, formatDatetime, formatDuration, formatDurationSeconds, formatFeeTier, formatGas, formatGwei, formatPerSecondRateWadAsAprPct, formatPerSecondRateWadAsApyPct, formatPoolIdHex, formatPriceRange, formatRateWad, formatRatioPercent, formatTick, formatTickRange, formatTimestamp, formatTimestampLocale, formatTokenAmount, formatTokenAmountSigned, formatTokenDelta, formatTokenFlow, formatTokenIdHex, formatTokenIdShort, formatTxHash, formatUtilization, formatWad, formatWadPercent, formatWadSigned, formatWei, generateOverlappingTokenIds, getAccountBuyingPower, getAccountCollateral, getAccountGreeks, getAccountHistory, getAccountPremia, getAccountSummaryBasic, getAccountSummaryRisk, getAssetIndex, getBlockMeta, getChainDeployment, getChunkLiquidities, getChunkSpreads, getClosedPositions, getClosedPositionsKey, getCollateralAddresses, getCollateralData, getCollateralSharePrices, getCollateralTotalAssetsBatch, getCurrentRates, getDeltaHedgeParams, getEnforcedTickLimits, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getForfeitablePremium, getGuardianUnlockState, getInterestState, getIrmCurrent, getIrmCurve, getItmAmounts, getLegDelta, getLegDeltaInVaultFrame, getLegGamma, getLegNetValueWidth0, getLegValue, getLiquidationPrices, getMarginBuffer, getMaxPositionSize, getMaxRedeem, getMaxWithdrawable, getNativeTokenPrice, getNetLiquidationValue, getNetLiquidationValues, getNotEnoughTokensError, getOpenPositionIds, getOpenPositionPreview, getOracleRiskParameters, getOracleState, getPanopticPoolAddress, getPanopticPoolFromPoolId, getPendingPositions, getPendingPositionsKey, getPool, getPoolDeploymentBlock, getPoolDisplayId, getPoolLiquidities, getPoolMetaKey, getPoolMetadata, getPoolPrefix, getPortfolioValue, getPosition, getPositionChunkData, getPositionEnrichmentData, getPositionGreeks, getPositionMetaKey, getPositions, getPositionsKey, getPositionsWithPremia, getPriceHistory, getPricesAtTick, getRealizedPnL, getRequiredCreditForITM, getRiskParameters, getSafeMode, getSchemaVersionKey, getStreamiaHistory, getSyncCheckpointKey, getSyncStatus, getTickSpacing, getTokenListId, getTrackedChunks, getTrackedChunksKey, getTrackedPositionIds, getTradeHistory, getUniswapFeeHistory, getUniswapV3LpPositionState, getUniswapV3PoolFromId, getUniswapV3PoolInfo, getUniswapV3PoolLiquidities, getUniswapV4LpPositionState, getUniswapV4PoolBasicState, getUniswapV4PoolInfo, getUniswapV4PoolKeyFromId, getUniswapV4PoolLiquidities, getUtilization, hasLoanOrCredit, hasLongLeg, interpolateBlocks, isCall, isCredit, isCreditLeg, isDefinedRisk, isGasError, isInputListFailError, isLiquidatable, isLoan, isLoanLeg, isNonceError, isPanopticErrorType, isPositionTracked, isRetryableRpcError, isShortOnly, isSpread, isSupportedChain, isolateGroupTokenId, jsonSerializer, ladderStrikeSequence, liquidate, liquidateAndWait, loadCheckpoint, minePoolAddress, mint, mintAndWait, mintableAfterBuffer, multicallRead, openPosition, openPositionAndWait, optimizeTokenIdRiskPartners, oracleEpochAt, orderListForSettle, packMarketState, panopticPoolV2Abi, parseBps, parseCollateralLog, parsePanopticError, parsePoolLog, parseTokenAmount, parseTokenListId, parseWad, planDeriveStrategy, pokeOracle, pokeOracleAndWait, previewBorrow, previewDeposit, previewMint, previewRedeem, previewUnwrap, previewWithdraw, previewWrap, priceToTick, publicBroadcaster, quoteOneTokenFlow, quoteSfpmSwap, quoteTemporaryLoanRecovery, quoteTokenShortfallRecovery, quoteV3ExactIn, ratePerSecWadToAprPct, reconstructFromEvents, recoverSnapshot, recoverSnapshotFromTx, redeem, redeemAndWait, removeTrackedChunks, repay, repayAndWait, requireChainDeployment, resolveBlockNumbers, resolveLadderStrike, resolvePanopticPoolFromPoolId, resolveTokenIndex, resolveUniswapV4PoolKey, riskEngineAbi, rollPosition, rollPositionAndWait, roundToTickSpacing, saveCheckpoint, saveClosedPosition, scanChunks, selectDispatchForAccount, settleAccumulatedPremia, settleAccumulatedPremiaAndWait, settlePremiumFrom, settlePremiumFromAndWait, simulateBatchDispatch, simulateClosePosition, simulateDeployNewPool, simulateDeposit, simulateDispatch, simulateForceExercise, simulateLiquidate, simulateOpenPosition, simulateSFPMBurn, simulateSFPMMint, simulateSettle, simulateSettlePremiumBatch, simulateSettlePremiumFrom, simulateSettleSequence, simulateSwapExactIn, simulateSwapExactOut, simulateWithTokenFlow, simulateWithdraw, slippageBpsToTickDistance, smartRepay, smartRepayAndWait, speedUpTransaction, splitTokenIdByTimescale, sqrtPriceX96ToPriceDecimalScaled, sqrtPriceX96ToTick, supply, supplyAndWait, swapExactIn, swapExactInAndWait, swapExactOut, swapExactOutAndWait, syncPositions, tickLimits, tickToPrice, tickToPriceDecimalScaled, tickToSqrtPriceX96, toVaultFrameAtTick, truncateAddress, unsupply, unsupplyAndWait, unwrapWeth, unwrapWethAndWait, unwrapXstock, unwrapXstockAndWait, utilizationBpsToWad, utilizationPctToWad, validateBatch, validateBuilderCode, validatePoolId, verifyBlockContinuity, watchEvents, wethWrapAbi, withdraw, withdrawAndWait, withdrawWithPositions, withdrawWithPositionsAndWait, wrapEth, wrapEthAndWait, wrapXstock, wrapXstockAndWait, xstockWrapperAbi };
|
|
29190
29822
|
//# sourceMappingURL=index.js.map
|