@panoptic-eng/sdk 1.0.39 → 1.0.41
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.d.ts.map +1 -1
- package/dist/cow/index.js +4 -0
- package/dist/cow/index.js.map +1 -1
- package/dist/index.d.ts +40 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +106 -3
- package/dist/index.js.map +1 -1
- package/dist/panoptic/v2/index.d.ts +117 -11
- package/dist/panoptic/v2/index.d.ts.map +1 -1
- package/dist/panoptic/v2/index.js +1589 -1367
- package/dist/panoptic/v2/index.js.map +1 -1
- package/dist/panoptic/v2/react-public.d.ts +117 -11
- package/dist/panoptic/v2/react-public.d.ts.map +1 -1
- package/dist/panoptic/v2/react-public.js +1822 -1600
- package/dist/panoptic/v2/react-public.js.map +1 -1
- package/dist/{transactionFees-C_Qx07mx.js → transactionFees-DUm6ilXB.js} +106 -2
- package/dist/uniswap/index.js +4 -0
- package/dist/uniswap/index.js.map +1 -1
- package/dist/{v2-DG7qG6di.js → v2-ChGyiigb.js} +224 -33
- package/dist/vault-transaction-fees.d.ts +41 -3
- package/dist/vault-transaction-fees.d.ts.map +1 -1
- package/dist/vault-transaction-fees.js +106 -2
- package/dist/vault-transaction-fees.js.map +1 -1
- package/dist/{writes-Xp9Wa8GQ.js → writes-_gfkBizf.js} +35 -4
- package/dist/zodiac/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { StateViewAbi, formatTokenAmount, getAccountCollateral, panopticQueryAbi$1 as panopticQueryAbi, parseTokenAmount, readBlockAndAggregate, requireReturnData } from "./irm-SPC2KxLA.js";
|
|
2
|
-
import { AccountInsolventError, ChunkLimitError, DEFAULT_VEGOID, InvalidHistoryRangeError, NotEnoughTokensError, PanopticError, PanopticValidationError, SafeModeError, StaleDataError, StorageDataNotFoundError, UnhealthyPoolError, WrongUniswapPoolError, collateralTrackerV2Abi, decodeLeftRightSigned, decodeLeftRightUnsigned, decodePosition, decodePositionBalance, decodeTickSpacing, getBlockMeta, getClosedPositionsKey, getPendingPositionsKey, getPool, getPoolMetaKey, getPositionMetaKey, getPositionsKey, getTrackedChunksKey, getTrackedPositionIds, jsonSerializer, mintableAfterBuffer, panopticFactoryV3Abi, panopticFactoryV4Abi, panopticGuardianAbi, panopticPoolV2Abi, panopticQueryAbi as panopticQueryAbi$1, parsePanopticError, riskEngineAbi, semiFungiblePositionManagerV3Abi, semiFungiblePositionManagerV4Abi, stateViewAbi, uniswapV3PoolAbi } from "./getTrackedPositionIds-ms3W9dYB.js";
|
|
2
|
+
import { AccountInsolventError, ChunkLimitError, DEFAULT_VEGOID, InvalidHistoryRangeError, LEG_LIMITS, NotEnoughTokensError, PanopticError, PanopticValidationError, SafeModeError, StaleDataError, StorageDataNotFoundError, TOKEN_ID_BITS, UnhealthyPoolError, WrongUniswapPoolError, collateralTrackerV2Abi, decodeLeftRightSigned, decodeLeftRightUnsigned, decodePosition, decodePositionBalance, decodeTickSpacing, getBlockMeta, getClosedPositionsKey, getPendingPositionsKey, getPool, getPoolMetaKey, getPositionMetaKey, getPositionsKey, getTrackedChunksKey, getTrackedPositionIds, jsonSerializer, mintableAfterBuffer, panopticFactoryV3Abi, panopticFactoryV4Abi, panopticGuardianAbi, panopticPoolV2Abi, panopticQueryAbi as panopticQueryAbi$1, parsePanopticError, riskEngineAbi, semiFungiblePositionManagerV3Abi, semiFungiblePositionManagerV4Abi, stateViewAbi, uniswapV3PoolAbi } from "./getTrackedPositionIds-ms3W9dYB.js";
|
|
3
3
|
import { MAX_TICK, MAX_TRACKED_CHUNKS, MIN_TICK, WAD, calculatePositionDelta, calculatePositionGamma, calculatePositionValue, priceToTick, sqrtPriceX96ToTick, tickLimits, tickToPrice, tickToPriceDecimalScaled, tickToSqrtPriceX96 } from "./greeks-GysWXct-.js";
|
|
4
|
-
import { addLegToTokenId, buildBatchDispatchArgs, buildUniqueCredit, countLegs, createTokenIdBuilder, decodeAllLegs, decodeTokenId, getPoolTokensForSimulation, loadCheckpoint, resolveTokenIndex, simulateOpenPosition, simulateWithTokenFlow } from "./writes-
|
|
4
|
+
import { addLegToTokenId, buildBatchDispatchArgs, buildUniqueCredit, countLegs, createTokenIdBuilder, decodeAllLegs, decodeTokenId, getCurrentPositionSizes, getPoolTokensForSimulation, loadCheckpoint, resolveTokenIndex, simulateOpenPosition, simulateWithTokenFlow } from "./writes-_gfkBizf.js";
|
|
5
5
|
import { BaseError, ContractFunctionExecutionError, ContractFunctionRevertedError, ExecutionRevertedError, decodeFunctionResult, encodeAbiParameters, encodeFunctionData, getAddress, keccak256, toHex, zeroAddress } from "viem";
|
|
6
6
|
import { multicall } from "viem/actions";
|
|
7
7
|
|
|
@@ -203,6 +203,165 @@ function interpolateBlocks(startBlock, endBlock, points) {
|
|
|
203
203
|
return Array.from({ length: points }, (_, i) => startBlock + range * BigInt(i) / BigInt(points - 1));
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region src/panoptic/v2/tokenId/deriveUniqueTokenId.ts
|
|
208
|
+
const POOL_ID_MASK$2 = (1n << 64n) - 1n;
|
|
209
|
+
const MAX_LEGS = TOKEN_ID_BITS.MAX_LEGS;
|
|
210
|
+
const MAX_OPTION_RATIO = LEG_LIMITS.MAX_RATIO;
|
|
211
|
+
const Q192$2 = 1n << 192n;
|
|
212
|
+
/**
|
|
213
|
+
* Floor integer square root for bigints (Newton's method). Mirrors the isqrt
|
|
214
|
+
* used in reads/collateralEstimate.ts (buildNeutralLeg).
|
|
215
|
+
*/
|
|
216
|
+
function isqrt$1(value) {
|
|
217
|
+
if (value < 0n) throw new PanopticError("isqrt of negative number");
|
|
218
|
+
if (value < 2n) return value;
|
|
219
|
+
let x = value;
|
|
220
|
+
let y = x + 1n >> 1n;
|
|
221
|
+
while (y < x) {
|
|
222
|
+
x = y;
|
|
223
|
+
y = x + value / x >> 1n;
|
|
224
|
+
}
|
|
225
|
+
return x;
|
|
226
|
+
}
|
|
227
|
+
const DEFAULT_TICK_SPACING = 200n;
|
|
228
|
+
/**
|
|
229
|
+
* Target notional (in wei of the tokenType-side asset) for the appended
|
|
230
|
+
* tiny credit leg. Chosen at 10 wei — small enough to be economically
|
|
231
|
+
* meaningless against any real position size, large enough to safely
|
|
232
|
+
* clear rounding on the SFPM's width-2 internal chunk math without any
|
|
233
|
+
* risk of underflowing to zero (which would revert ChunkHasZeroLiquidity).
|
|
234
|
+
*/
|
|
235
|
+
const TINY_CREDIT_TARGET_NOTIONAL_WEI = 10n;
|
|
236
|
+
/**
|
|
237
|
+
* Pick a signedStrike for the appended width=0 credit leg such that:
|
|
238
|
+
* 1. positionSize · 1.0001^signedStrike ≈ TINY_CREDIT_TARGET_NOTIONAL_WEI
|
|
239
|
+
* (~10 wei — economically meaningless but comfortably above any
|
|
240
|
+
* SFPM width-2 chunk rounding);
|
|
241
|
+
* 2. the leg's tick range (SFPM internally treats width=0 as width=2, so
|
|
242
|
+
* the range is `strike ± tickSpacing`) stays strictly inside
|
|
243
|
+
* `[MIN_POOL_TICK, MAX_POOL_TICK]` — otherwise the getSqrtRatioAtTick
|
|
244
|
+
* call reverts with `InvalidTick`.
|
|
245
|
+
*
|
|
246
|
+
* Closed form: `1.0001^signedStrike = target/positionSize`, so
|
|
247
|
+
* `sqrtKrawX96 = isqrt(target · 2^192 / positionSize)` and
|
|
248
|
+
* `signedStrike = sqrtPriceX96ToTick(sqrtKrawX96)`. If the notional-optimal
|
|
249
|
+
* strike falls outside the safe range, we clamp inward. Clamping raises the
|
|
250
|
+
* notional but keeps it << position size for any reasonable strike.
|
|
251
|
+
*/
|
|
252
|
+
function computeTinyCreditSignedStrike(positionSize, tickSpacing) {
|
|
253
|
+
if (positionSize <= 0n) throw new PanopticError("computeTinyCreditSignedStrike: positionSize must be > 0");
|
|
254
|
+
const minSafe = MIN_TICK + tickSpacing + 1n;
|
|
255
|
+
const maxSafe = MAX_TICK - tickSpacing - 1n;
|
|
256
|
+
let signedStrike;
|
|
257
|
+
try {
|
|
258
|
+
const sqrtKrawX96 = isqrt$1(TINY_CREDIT_TARGET_NOTIONAL_WEI * Q192$2 / positionSize);
|
|
259
|
+
signedStrike = sqrtPriceX96ToTick(sqrtKrawX96);
|
|
260
|
+
} catch {
|
|
261
|
+
signedStrike = minSafe;
|
|
262
|
+
}
|
|
263
|
+
if (signedStrike < minSafe) return minSafe;
|
|
264
|
+
if (signedStrike > maxSafe) return maxSafe;
|
|
265
|
+
return signedStrike;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Assemble the tiny credit leg struct, picking a strike that avoids
|
|
269
|
+
* colliding with any existing width=0 credit leg on the same (asset,
|
|
270
|
+
* tokenType) pair.
|
|
271
|
+
*
|
|
272
|
+
* The encoded strike stored in the tokenId is
|
|
273
|
+
* `asset === 0 ? signedStrike : -signedStrike` (mirrors
|
|
274
|
+
* {@link buildNeutralLeg} in reads/collateralEstimate.ts).
|
|
275
|
+
*/
|
|
276
|
+
function pickUniqueTinyCreditLeg(baseTokenId, legIndex, positionSize, tickSpacing) {
|
|
277
|
+
const asset = 1n;
|
|
278
|
+
const tokenType = 0n;
|
|
279
|
+
const existingLegs = decodeAllLegs(baseTokenId);
|
|
280
|
+
const maxSafe = MAX_TICK - tickSpacing - 1n;
|
|
281
|
+
let signedStrike = computeTinyCreditSignedStrike(positionSize, tickSpacing);
|
|
282
|
+
while (signedStrike <= maxSafe) {
|
|
283
|
+
const candidate = asset === 0n ? signedStrike : -signedStrike;
|
|
284
|
+
let collides = false;
|
|
285
|
+
for (const leg of existingLegs) if (leg.width === 0n && leg.isLong && leg.asset === asset && leg.tokenType === tokenType && leg.strike === candidate) {
|
|
286
|
+
collides = true;
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
if (!collides) break;
|
|
290
|
+
signedStrike += 1n;
|
|
291
|
+
}
|
|
292
|
+
if (signedStrike > maxSafe) throw new PanopticError("deriveUniqueTokenId: exhausted strike space picking a unique tiny credit leg");
|
|
293
|
+
const encodedStrike = asset === 0n ? signedStrike : -signedStrike;
|
|
294
|
+
return {
|
|
295
|
+
index: legIndex,
|
|
296
|
+
asset,
|
|
297
|
+
tokenType,
|
|
298
|
+
optionRatio: 1n,
|
|
299
|
+
isLong: 1n,
|
|
300
|
+
riskPartner: legIndex,
|
|
301
|
+
strike: encodedStrike,
|
|
302
|
+
width: 0n
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
function appendTinyCreditLeg(baseTokenId, baseLegCount, positionSize, tickSpacing) {
|
|
306
|
+
const newLeg = pickUniqueTinyCreditLeg(baseTokenId, baseLegCount, positionSize, tickSpacing);
|
|
307
|
+
return addLegToTokenId(baseTokenId, newLeg);
|
|
308
|
+
}
|
|
309
|
+
function scaleRatios(baseTokenId, targetPositionSize) {
|
|
310
|
+
const legs = decodeAllLegs(baseTokenId);
|
|
311
|
+
const maxRatio = legs.reduce((m, leg) => leg.optionRatio > m ? leg.optionRatio : m, 0n);
|
|
312
|
+
const N = MAX_OPTION_RATIO / maxRatio;
|
|
313
|
+
if (N < 2n) throw new PanopticError("deriveUniqueTokenId: cannot derive a unique tokenId — all 4 leg slots used and optionRatios already near the 127 ceiling");
|
|
314
|
+
const newPositionSize = (targetPositionSize + N - 1n) / N;
|
|
315
|
+
const poolId = baseTokenId & POOL_ID_MASK$2;
|
|
316
|
+
let out = poolId;
|
|
317
|
+
for (const leg of legs) out = addLegToTokenId(out, {
|
|
318
|
+
index: leg.index,
|
|
319
|
+
asset: leg.asset,
|
|
320
|
+
tokenType: leg.tokenType,
|
|
321
|
+
optionRatio: leg.optionRatio * N,
|
|
322
|
+
isLong: leg.isLong ? 1n : 0n,
|
|
323
|
+
riskPartner: leg.riskPartner,
|
|
324
|
+
strike: leg.strike,
|
|
325
|
+
width: leg.width
|
|
326
|
+
});
|
|
327
|
+
return {
|
|
328
|
+
newTokenId: out,
|
|
329
|
+
newPositionSize,
|
|
330
|
+
effectivePositionSize: newPositionSize * N,
|
|
331
|
+
strategy: "ratio-scale"
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Derive a tokenId unique from `baseTokenId` for a partial reduction.
|
|
336
|
+
*
|
|
337
|
+
* Prefers a tiny-credit-leg extension (arbitrary new size). Falls back to
|
|
338
|
+
* optionRatio scaling only when the base tokenId already occupies all 4 leg
|
|
339
|
+
* slots.
|
|
340
|
+
*/
|
|
341
|
+
function deriveUniqueTokenId(params) {
|
|
342
|
+
const { baseTokenId, targetPositionSize, tickSpacing = DEFAULT_TICK_SPACING } = params;
|
|
343
|
+
if (targetPositionSize <= 0n) throw new PanopticError("deriveUniqueTokenId: targetPositionSize must be > 0");
|
|
344
|
+
const legCount = countLegs(baseTokenId);
|
|
345
|
+
if (legCount === 0n) throw new PanopticError("deriveUniqueTokenId: baseTokenId has no legs");
|
|
346
|
+
if (legCount < MAX_LEGS) {
|
|
347
|
+
const newTokenId = appendTinyCreditLeg(baseTokenId, legCount, targetPositionSize, tickSpacing);
|
|
348
|
+
return {
|
|
349
|
+
newTokenId,
|
|
350
|
+
newPositionSize: targetPositionSize,
|
|
351
|
+
effectivePositionSize: targetPositionSize,
|
|
352
|
+
strategy: "tiny-credit"
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
return scaleRatios(baseTokenId, targetPositionSize);
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Re-export decoded leg count so callers can gate UI on the strategy that
|
|
359
|
+
* would be chosen (e.g. show a divisibility hint on ratio-scale positions).
|
|
360
|
+
*/
|
|
361
|
+
function planDeriveStrategy(baseTokenId) {
|
|
362
|
+
return countLegs(baseTokenId) < MAX_LEGS ? "tiny-credit" : "ratio-scale";
|
|
363
|
+
}
|
|
364
|
+
|
|
206
365
|
//#endregion
|
|
207
366
|
//#region src/panoptic/v2/sfpmSwap/calldata.ts
|
|
208
367
|
/**
|
|
@@ -1703,8 +1862,9 @@ async function quoteTokenShortfallRecovery(params) {
|
|
|
1703
1862
|
error: new PanopticError("Could not size the prefixed recovery swap")
|
|
1704
1863
|
};
|
|
1705
1864
|
};
|
|
1865
|
+
let creditOutSize = amountOut;
|
|
1706
1866
|
for (let attempt = 0; attempt < MAX_RECOVERY_QUOTE_ATTEMPTS; attempt++) {
|
|
1707
|
-
const credit = buildUniqueCredit(pool.poolId, tokenOutIndex, tokenOutIndex, pool.currentTick, pool.tickSpacing, collisionIds,
|
|
1867
|
+
const credit = buildUniqueCredit(pool.poolId, tokenOutIndex, tokenOutIndex, pool.currentTick, pool.tickSpacing, collisionIds, creditOutSize);
|
|
1708
1868
|
const recoveredDispatch = buildTokenShortfallRecoveryDispatch({
|
|
1709
1869
|
dispatch: params.dispatch,
|
|
1710
1870
|
creditTokenId: credit.tokenId,
|
|
@@ -1748,10 +1908,14 @@ async function quoteTokenShortfallRecovery(params) {
|
|
|
1748
1908
|
const maxAmountIn = maximumAmountIn(estimatedAmountIn, params.slippageBps);
|
|
1749
1909
|
const swapOutput = getOutputAmount(swapSimulation.tokenFlow, tokenOutIndex);
|
|
1750
1910
|
const sourceBalance = getBalanceBefore(swapSimulation.tokenFlow, tokenInIndex);
|
|
1751
|
-
if (swapOutput < amountOut
|
|
1911
|
+
if (swapOutput < amountOut) {
|
|
1912
|
+
creditOutSize = swapOutput > 0n ? ceilDiv(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
|
|
1913
|
+
continue;
|
|
1914
|
+
}
|
|
1915
|
+
if (sourceBalance < maxAmountIn) return {
|
|
1752
1916
|
available: false,
|
|
1753
1917
|
reason: "swap-unavailable",
|
|
1754
|
-
detail:
|
|
1918
|
+
detail: `source balance ${sourceBalance} < maximumAmountIn ${maxAmountIn} (estimated ${estimatedAmountIn}, slippageBps ${params.slippageBps})`,
|
|
1755
1919
|
error: new PanopticError("Insufficient source collateral for the recovery swap")
|
|
1756
1920
|
};
|
|
1757
1921
|
const recoverySimulation = await simulateDispatch({
|
|
@@ -1803,6 +1967,7 @@ async function quoteTokenShortfallRecovery(params) {
|
|
|
1803
1967
|
const decodedShortfall = remainingShortfall.assetsRequested - remainingShortfall.assetBalance;
|
|
1804
1968
|
const additionalAmountOut = decodedShortfall > 0n ? decodedShortfall : amountOut;
|
|
1805
1969
|
amountOut += additionalAmountOut;
|
|
1970
|
+
creditOutSize = swapOutput > 0n ? ceilDiv(creditOutSize * amountOut, swapOutput) + 1n : creditOutSize * 2n;
|
|
1806
1971
|
}
|
|
1807
1972
|
return {
|
|
1808
1973
|
available: false,
|
|
@@ -1829,6 +1994,7 @@ const MAX_EFFECTIVE_LIQUIDITY_LIMIT = 8388607;
|
|
|
1829
1994
|
* returned value must be scaled down to the caller's actual `positionSize`.
|
|
1830
1995
|
*/
|
|
1831
1996
|
const MAX_UINT64$1 = 2n ** 64n - 1n;
|
|
1997
|
+
const FP96$1 = 1n << 96n;
|
|
1832
1998
|
/**
|
|
1833
1999
|
* `getRequiredBase` returns `type(uint128).max` as an error sentinel (invalid
|
|
1834
2000
|
* tokenId or reverting `getMargin`). Detect it so we don't scale a garbage value.
|
|
@@ -1841,7 +2007,9 @@ const REQUIRED_BASE_ERROR_SENTINEL = 2n ** 128n - 1n;
|
|
|
1841
2007
|
* computes the requirement at `type(uint64).max` size and 0% utilization. Since
|
|
1842
2008
|
* the requirement is linear in size, the raw result is scaled by
|
|
1843
2009
|
* `positionSize / type(uint64).max` to yield the requirement for the requested
|
|
1844
|
-
* size.
|
|
2010
|
+
* size. `PanopticQuery.getRequiredBase` returns the cross-margin requirement in
|
|
2011
|
+
* the higher-precision raw token at `atTick`; this function places that amount
|
|
2012
|
+
* in the matching `required0` or `required1` field.
|
|
1845
2013
|
*
|
|
1846
2014
|
* @param params - The parameters
|
|
1847
2015
|
* @returns Estimated collateral requirements with block metadata
|
|
@@ -1860,7 +2028,7 @@ async function estimateCollateralRequired(params) {
|
|
|
1860
2028
|
});
|
|
1861
2029
|
effectiveTick = BigInt(currentTickResult);
|
|
1862
2030
|
}
|
|
1863
|
-
const [
|
|
2031
|
+
const [requiredBase, _meta] = await Promise.all([client.readContract({
|
|
1864
2032
|
address: queryAddress,
|
|
1865
2033
|
abi: panopticQueryAbi,
|
|
1866
2034
|
functionName: "getRequiredBase",
|
|
@@ -1874,10 +2042,11 @@ async function estimateCollateralRequired(params) {
|
|
|
1874
2042
|
client,
|
|
1875
2043
|
blockNumber: targetBlockNumber
|
|
1876
2044
|
})]);
|
|
1877
|
-
const
|
|
2045
|
+
const scaledRequirement = requiredBase >= REQUIRED_BASE_ERROR_SENTINEL ? requiredBase : requiredBase * positionSize / MAX_UINT64$1;
|
|
2046
|
+
const denominatedInToken0 = tickToSqrtPriceX96(effectiveTick) < FP96$1;
|
|
1878
2047
|
return {
|
|
1879
|
-
required0:
|
|
1880
|
-
required1: 0n,
|
|
2048
|
+
required0: denominatedInToken0 ? scaledRequirement : 0n,
|
|
2049
|
+
required1: denominatedInToken0 ? 0n : scaledRequirement,
|
|
1881
2050
|
_meta
|
|
1882
2051
|
};
|
|
1883
2052
|
}
|
|
@@ -5089,7 +5258,9 @@ async function getStreamiaHistory(params) {
|
|
|
5089
5258
|
_meta: _meta$1
|
|
5090
5259
|
};
|
|
5091
5260
|
}
|
|
5092
|
-
const
|
|
5261
|
+
const _meta = params._meta ?? await getBlockMeta({ client });
|
|
5262
|
+
const resolvedBlockNumbers = blockNumbers.map((blockNumber) => blockNumber ?? _meta.blockNumber);
|
|
5263
|
+
const premiaRequests = resolvedBlockNumbers.map((blockNumber) => client.readContract({
|
|
5093
5264
|
address: panopticPoolAddress,
|
|
5094
5265
|
abi: panopticPoolV2Abi,
|
|
5095
5266
|
functionName: "getFullPositionsData",
|
|
@@ -5098,18 +5269,36 @@ async function getStreamiaHistory(params) {
|
|
|
5098
5269
|
true,
|
|
5099
5270
|
[tokenId]
|
|
5100
5271
|
],
|
|
5101
|
-
blockNumber
|
|
5272
|
+
blockNumber
|
|
5102
5273
|
}));
|
|
5103
|
-
const uniswapDataPromise = includeUniswapFees && legs.length > 0 ? fetchUniswapFeeData(client,
|
|
5104
|
-
const [premiaResults, uniswapData
|
|
5105
|
-
|
|
5106
|
-
uniswapDataPromise ?? Promise.resolve(void 0),
|
|
5107
|
-
params._meta ? Promise.resolve(params._meta) : getBlockMeta({ client })
|
|
5108
|
-
]);
|
|
5109
|
-
const sortedSettled = settledEvents ? [...settledEvents].sort((a, b) => a.blockNumber < b.blockNumber ? -1 : 1) : [];
|
|
5274
|
+
const uniswapDataPromise = includeUniswapFees && legs.length > 0 ? fetchUniswapFeeData(client, resolvedBlockNumbers, legs, poolConfig) : void 0;
|
|
5275
|
+
const [premiaResults, uniswapData] = await Promise.all([Promise.all(premiaRequests), uniswapDataPromise ?? Promise.resolve(void 0)]);
|
|
5276
|
+
const sortedSettled = settledEvents ? [...settledEvents].sort((a, b) => a.blockNumber === b.blockNumber ? 0 : a.blockNumber < b.blockNumber ? -1 : 1) : [];
|
|
5110
5277
|
let settledIdx = 0;
|
|
5111
5278
|
let accSettled0 = 0n;
|
|
5112
5279
|
let accSettled1 = 0n;
|
|
5280
|
+
const cumulativePremiaByInputIndex = Array.from({ length: blockNumbers.length }, () => ({
|
|
5281
|
+
token0: 0n,
|
|
5282
|
+
token1: 0n
|
|
5283
|
+
}));
|
|
5284
|
+
const chronologicalInputs = resolvedBlockNumbers.map((blockNumber, inputIndex) => ({
|
|
5285
|
+
blockNumber,
|
|
5286
|
+
inputIndex
|
|
5287
|
+
})).sort((a, b) => a.blockNumber === b.blockNumber ? a.inputIndex - b.inputIndex : a.blockNumber < b.blockNumber ? -1 : 1);
|
|
5288
|
+
for (const { blockNumber, inputIndex } of chronologicalInputs) {
|
|
5289
|
+
while (settledIdx < sortedSettled.length && sortedSettled[settledIdx].blockNumber <= blockNumber) {
|
|
5290
|
+
accSettled0 += sortedSettled[settledIdx].settled0;
|
|
5291
|
+
accSettled1 += sortedSettled[settledIdx].settled1;
|
|
5292
|
+
settledIdx++;
|
|
5293
|
+
}
|
|
5294
|
+
const result = premiaResults[inputIndex];
|
|
5295
|
+
const premia0 = (result[0] & MASK_128) - (result[1] & MASK_128);
|
|
5296
|
+
const premia1 = (result[0] >> 128n) - (result[1] >> 128n);
|
|
5297
|
+
cumulativePremiaByInputIndex[inputIndex] = {
|
|
5298
|
+
token0: premia0 + accSettled0,
|
|
5299
|
+
token1: premia1 + accSettled1
|
|
5300
|
+
};
|
|
5301
|
+
}
|
|
5113
5302
|
let initialUniswapFees0 = null;
|
|
5114
5303
|
let initialUniswapFees1 = null;
|
|
5115
5304
|
const snapshots = premiaResults.map((result, i) => {
|
|
@@ -5120,14 +5309,8 @@ async function getStreamiaHistory(params) {
|
|
|
5120
5309
|
const short1 = shortPacked >> 128n;
|
|
5121
5310
|
const long0 = longPacked & MASK_128;
|
|
5122
5311
|
const long1 = longPacked >> 128n;
|
|
5123
|
-
const
|
|
5124
|
-
|
|
5125
|
-
accSettled0 += sortedSettled[settledIdx].settled0;
|
|
5126
|
-
accSettled1 += sortedSettled[settledIdx].settled1;
|
|
5127
|
-
settledIdx++;
|
|
5128
|
-
}
|
|
5129
|
-
const premia0 = short0 - long0 - accSettled0;
|
|
5130
|
-
const premia1 = short1 - long1 - accSettled1;
|
|
5312
|
+
const premia0 = short0 - long0;
|
|
5313
|
+
const premia1 = short1 - long1;
|
|
5131
5314
|
let uniswapFees0 = 0n;
|
|
5132
5315
|
let uniswapFees1 = 0n;
|
|
5133
5316
|
if (uniswapData) {
|
|
@@ -5146,6 +5329,7 @@ async function getStreamiaHistory(params) {
|
|
|
5146
5329
|
token0: premia0,
|
|
5147
5330
|
token1: premia1
|
|
5148
5331
|
},
|
|
5332
|
+
cumulativePanopticPremia: cumulativePremiaByInputIndex[i],
|
|
5149
5333
|
uniswapFees: {
|
|
5150
5334
|
token0: uniswapFees0,
|
|
5151
5335
|
token1: uniswapFees1
|
|
@@ -6932,14 +7116,21 @@ const multicallAbi = [{
|
|
|
6932
7116
|
* @returns Simulation result with settlement data or error
|
|
6933
7117
|
*/
|
|
6934
7118
|
async function simulateSettle(params) {
|
|
6935
|
-
const { client, poolAddress, account, positionIdList, tokenId, blockNumber } = params;
|
|
7119
|
+
const { client, poolAddress, account, positionIdList, finalPositionIdList, positionSizes: providedSizes, tokenId, blockNumber } = params;
|
|
6936
7120
|
const targetBlockNumber = blockNumber ?? await client.getBlockNumber();
|
|
6937
7121
|
const metaPromise = getBlockMeta({
|
|
6938
7122
|
client,
|
|
6939
7123
|
blockNumber: targetBlockNumber
|
|
6940
7124
|
});
|
|
6941
7125
|
try {
|
|
6942
|
-
|
|
7126
|
+
if (providedSizes && providedSizes.length !== positionIdList.length) throw new PanopticError("simulateSettle: positionSizes length must match positionIdList");
|
|
7127
|
+
const positionSizes = providedSizes ?? await getCurrentPositionSizes({
|
|
7128
|
+
client,
|
|
7129
|
+
poolAddress,
|
|
7130
|
+
account,
|
|
7131
|
+
positionIdList,
|
|
7132
|
+
blockNumber: targetBlockNumber
|
|
7133
|
+
});
|
|
6943
7134
|
const tickAndSpreadLimits = positionIdList.map(() => [
|
|
6944
7135
|
-887272n,
|
|
6945
7136
|
887272n,
|
|
@@ -6950,7 +7141,7 @@ async function simulateSettle(params) {
|
|
|
6950
7141
|
functionName: "dispatch",
|
|
6951
7142
|
args: [
|
|
6952
7143
|
positionIdList,
|
|
6953
|
-
positionIdList,
|
|
7144
|
+
finalPositionIdList ?? positionIdList,
|
|
6954
7145
|
positionSizes.map((s) => BigInt(s)),
|
|
6955
7146
|
tickAndSpreadLimits.map((t) => [
|
|
6956
7147
|
Number(t[0]),
|
|
@@ -6982,8 +7173,8 @@ async function simulateSettle(params) {
|
|
|
6982
7173
|
});
|
|
6983
7174
|
const _meta = await metaPromise;
|
|
6984
7175
|
const data = {
|
|
6985
|
-
premiaReceived0: tokenFlow.delta0
|
|
6986
|
-
premiaReceived1: tokenFlow.delta1
|
|
7176
|
+
premiaReceived0: tokenFlow.delta0,
|
|
7177
|
+
premiaReceived1: tokenFlow.delta1,
|
|
6987
7178
|
postCollateral0: tokenFlow.balanceAfter0,
|
|
6988
7179
|
postCollateral1: tokenFlow.balanceAfter1,
|
|
6989
7180
|
forfeitAmounts
|
|
@@ -9100,4 +9291,4 @@ function isGasError(error) {
|
|
|
9100
9291
|
}
|
|
9101
9292
|
|
|
9102
9293
|
//#endregion
|
|
9103
|
-
export { DEFAULT_MIN_SWAP_RATIO_BPS, DEFAULT_RECONNECT_CONFIG, REQUIRED_BASE_ERROR_SENTINEL, addPendingPosition, addTrackedChunks, apportion, assertCanBurn, assertCanForceExercise, assertCanLiquidate, assertCanMint, assertFresh, assertHealthy, assertTradeable, buildCreditWrappedDispatch, buildSfpmSwapCalldata, buildSfpmSwapPlan, buildTokenShortfallRecoveryDispatch, calculateAccountGreeksPure, calculateSpreadWad, checkCollateralAcrossTicks, classifyStrategyGroups, cleanupStalePendingPositions, clearPendingPositions, clearTrackedChunks, clearTradeHistory, collateralRuleKindFor, computeV4PoolId, confirmPendingPosition, convertToAssets, convertToShares, createEventPoller, createEventSubscription, createFlowNeutralTokenId, createPoolFormatters, decodePanopticTokenURI, encodePoolKeyBytes, encodeV3PoolKeyBytes, ensureSfpmV3PoolInitialized, estimateBlockNumbers, estimateCollateralBreakdown, estimateCollateralRequired, failPendingPosition, feesFromFeeGrowthDelta, fetchSfpmV3PoolId, formatBlockNumber, formatBps, formatCompact, formatDatetime, formatDuration, formatDurationSeconds, formatFeeTier, formatGas, formatGwei, formatPoolIdHex, formatRatioPercent, formatTimestamp, formatTimestampLocale, formatTokenIdHex, formatTokenIdShort, formatTxHash, formatUtilization, formatWei, getAccountBuyingPower, getAccountGreeks, getAccountHistory, getAccountPremia, getChunkLiquidities, getChunkSpreads, getClosedPositions, getCollateralSharePrices, getCollateralTotalAssetsBatch, getDeltaHedgeParams, getEnforcedTickLimits, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getGuardianUnlockState, getItmAmounts, getMarginBuffer, getMaxPositionSize, getMaxRedeem, getMaxWithdrawable, getNativeTokenPrice, getNotEnoughTokensError, getOpenPositionPreview, getPanopticPoolAddress, getPanopticPoolFromPoolId, getPendingPositions, getPoolDisplayId, getPoolLiquidities, getPortfolioValue, getPositionChunkData, getPositionEnrichmentData, getPositionsWithPremia, getPriceHistory, getRealizedPnL, getRequiredCreditForITM, getSafeMode, getStreamiaHistory, getSyncStatus, getTokenListId, getTrackedChunks, getTradeHistory, getUniswapFeeHistory, getUniswapV3LpPositionState, getUniswapV3PoolFromId, getUniswapV3PoolInfo, getUniswapV3PoolLiquidities, getUniswapV4LpPositionState, getUniswapV4PoolBasicState, getUniswapV4PoolInfo, getUniswapV4PoolKeyFromId, getUniswapV4PoolLiquidities, interpolateBlocks, isGasError, isNonceError, isRetryableRpcError, isolateGroupTokenId, minePoolAddress, minePoolAddressLocalAsync, multicallRead, optimizeTokenIdRiskPartners, parseBps, parseCollateralLog, parsePoolLog, parseTokenListId, previewDeposit, previewMint, previewRedeem, previewWithdraw, quoteOneTokenFlow, quoteSfpmSwap, quoteTokenShortfallRecovery, removeTrackedChunks, resolveBlockNumbers, resolvePanopticPoolFromPoolId, resolveUniswapV4PoolKey, saveClosedPosition, scanChunks, simulateBatchDispatch, simulateClosePosition, simulateDeployNewPool, simulateDeposit, simulateDispatch, simulateForceExercise, simulateLiquidate, simulateSFPMBurn, simulateSFPMMint, simulateSettle, simulateSwapExactIn, simulateSwapExactOut, simulateWithdraw, slippageBpsToTickDistance, truncateAddress, watchEvents };
|
|
9294
|
+
export { DEFAULT_MIN_SWAP_RATIO_BPS, DEFAULT_RECONNECT_CONFIG, REQUIRED_BASE_ERROR_SENTINEL, addPendingPosition, addTrackedChunks, apportion, assertCanBurn, assertCanForceExercise, assertCanLiquidate, assertCanMint, assertFresh, assertHealthy, assertTradeable, buildCreditWrappedDispatch, buildSfpmSwapCalldata, buildSfpmSwapPlan, buildTokenShortfallRecoveryDispatch, calculateAccountGreeksPure, calculateSpreadWad, checkCollateralAcrossTicks, classifyStrategyGroups, cleanupStalePendingPositions, clearPendingPositions, clearTrackedChunks, clearTradeHistory, collateralRuleKindFor, computeV4PoolId, confirmPendingPosition, convertToAssets, convertToShares, createEventPoller, createEventSubscription, createFlowNeutralTokenId, createPoolFormatters, decodePanopticTokenURI, deriveUniqueTokenId, encodePoolKeyBytes, encodeV3PoolKeyBytes, ensureSfpmV3PoolInitialized, estimateBlockNumbers, estimateCollateralBreakdown, estimateCollateralRequired, failPendingPosition, feesFromFeeGrowthDelta, fetchSfpmV3PoolId, formatBlockNumber, formatBps, formatCompact, formatDatetime, formatDuration, formatDurationSeconds, formatFeeTier, formatGas, formatGwei, formatPoolIdHex, formatRatioPercent, formatTimestamp, formatTimestampLocale, formatTokenIdHex, formatTokenIdShort, formatTxHash, formatUtilization, formatWei, getAccountBuyingPower, getAccountGreeks, getAccountHistory, getAccountPremia, getChunkLiquidities, getChunkSpreads, getClosedPositions, getCollateralSharePrices, getCollateralTotalAssetsBatch, getDeltaHedgeParams, getEnforcedTickLimits, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getGuardianUnlockState, getItmAmounts, getMarginBuffer, getMaxPositionSize, getMaxRedeem, getMaxWithdrawable, getNativeTokenPrice, getNotEnoughTokensError, getOpenPositionPreview, getPanopticPoolAddress, getPanopticPoolFromPoolId, getPendingPositions, getPoolDisplayId, getPoolLiquidities, getPortfolioValue, getPositionChunkData, getPositionEnrichmentData, getPositionsWithPremia, getPriceHistory, getRealizedPnL, getRequiredCreditForITM, getSafeMode, getStreamiaHistory, getSyncStatus, getTokenListId, getTrackedChunks, getTradeHistory, getUniswapFeeHistory, getUniswapV3LpPositionState, getUniswapV3PoolFromId, getUniswapV3PoolInfo, getUniswapV3PoolLiquidities, getUniswapV4LpPositionState, getUniswapV4PoolBasicState, getUniswapV4PoolInfo, getUniswapV4PoolKeyFromId, getUniswapV4PoolLiquidities, interpolateBlocks, isGasError, isNonceError, isRetryableRpcError, isolateGroupTokenId, minePoolAddress, minePoolAddressLocalAsync, multicallRead, optimizeTokenIdRiskPartners, parseBps, parseCollateralLog, parsePoolLog, parseTokenListId, planDeriveStrategy, previewDeposit, previewMint, previewRedeem, previewWithdraw, quoteOneTokenFlow, quoteSfpmSwap, quoteTokenShortfallRecovery, removeTrackedChunks, resolveBlockNumbers, resolvePanopticPoolFromPoolId, resolveUniswapV4PoolKey, saveClosedPosition, scanChunks, simulateBatchDispatch, simulateClosePosition, simulateDeployNewPool, simulateDeposit, simulateDispatch, simulateForceExercise, simulateLiquidate, simulateSFPMBurn, simulateSFPMMint, simulateSettle, simulateSwapExactIn, simulateSwapExactOut, simulateWithdraw, slippageBpsToTickDistance, truncateAddress, watchEvents };
|
|
@@ -8,7 +8,10 @@ type VaultTransactionFeeQuote = {
|
|
|
8
8
|
maxFeePerGas: bigint;
|
|
9
9
|
maxPriorityFeePerGas: bigint;
|
|
10
10
|
minimumMaxFeePerGas: bigint;
|
|
11
|
-
source: 'fee_history' | 'viem_fallback';
|
|
11
|
+
source: 'fee_history' | 'viem_fallback' | 'rpc_priority_fee' | 'fee_history_p25';
|
|
12
|
+
};
|
|
13
|
+
type VaultDeltaHedgeFeeQuote = VaultTransactionFeeQuote & {
|
|
14
|
+
rawPriorityFeePerGas: bigint;
|
|
12
15
|
};
|
|
13
16
|
type VaultSignedTransactionFeeCaps = {
|
|
14
17
|
gasLimit?: bigint | null;
|
|
@@ -47,6 +50,34 @@ declare class VaultTransactionGasCostLimitError extends Error {
|
|
|
47
50
|
minimumRequiredFeePerGas: bigint;
|
|
48
51
|
});
|
|
49
52
|
}
|
|
53
|
+
declare class VaultTransactionReplacementLimitError extends Error {
|
|
54
|
+
readonly code: 'GasCostCapExceeded';
|
|
55
|
+
readonly requiredMaxFeePerGas: bigint;
|
|
56
|
+
readonly requiredMaxPriorityFeePerGas: bigint;
|
|
57
|
+
readonly maximumAffordableFeePerGas: bigint;
|
|
58
|
+
constructor({
|
|
59
|
+
code,
|
|
60
|
+
gasLimit,
|
|
61
|
+
requiredMaxFeePerGas,
|
|
62
|
+
requiredMaxPriorityFeePerGas,
|
|
63
|
+
maximumAffordableFeePerGas
|
|
64
|
+
}: {
|
|
65
|
+
code: 'GasCostCapExceeded';
|
|
66
|
+
gasLimit: bigint;
|
|
67
|
+
requiredMaxFeePerGas: bigint;
|
|
68
|
+
requiredMaxPriorityFeePerGas: bigint;
|
|
69
|
+
maximumAffordableFeePerGas: bigint;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
declare function getVaultTransactionReplacementFeeQuote({
|
|
73
|
+
originalQuote,
|
|
74
|
+
historicalQuote,
|
|
75
|
+
gasLimit
|
|
76
|
+
}: {
|
|
77
|
+
originalQuote: Pick<VaultTransactionFeeQuote, 'maxFeePerGas' | 'maxPriorityFeePerGas'>;
|
|
78
|
+
historicalQuote: VaultDeltaHedgeFeeQuote;
|
|
79
|
+
gasLimit: bigint;
|
|
80
|
+
}): VaultDeltaHedgeFeeQuote;
|
|
50
81
|
declare function applyVaultTransactionGasCostLimit(quote: VaultTransactionFeeQuote, gasLimit: bigint): VaultTransactionFeeQuote;
|
|
51
82
|
declare function bufferVaultTransactionGasEstimate(gasEstimate: bigint): bigint;
|
|
52
83
|
declare function validateVaultSignedTransactionFeeCaps(feeCaps: VaultSignedTransactionFeeCaps, quote?: VaultTransactionFeeQuote): VaultSignedTransactionFeeValidationResult;
|
|
@@ -58,6 +89,13 @@ declare function validateVaultSignedTransactionFeeCaps(feeCaps: VaultSignedTrans
|
|
|
58
89
|
* Viem's estimate is used while preserving those bounds and its original
|
|
59
90
|
* base-fee allowance.
|
|
60
91
|
*/
|
|
61
|
-
declare function getVaultTransactionFeeQuote<chain extends Chain | undefined>(client: Client<Transport, chain>): Promise<VaultTransactionFeeQuote>;
|
|
62
|
-
|
|
92
|
+
declare function getVaultTransactionFeeQuote<chain extends Chain | undefined>(client: Client<Transport, chain>): Promise<VaultTransactionFeeQuote>;
|
|
93
|
+
declare function getVaultDeltaHedgeHistoricalFeeQuote<chain extends Chain | undefined>(client: Client<Transport, chain>): Promise<VaultDeltaHedgeFeeQuote>;
|
|
94
|
+
/**
|
|
95
|
+
* Resolve the first fee quote for a delta hedge from the connected RPC's
|
|
96
|
+
* eth_maxPriorityFeePerGas recommendation. A failed RPC recommendation falls
|
|
97
|
+
* back immediately to the rolling historical p25 quote.
|
|
98
|
+
*/
|
|
99
|
+
declare function getVaultDeltaHedgeInitialFeeQuote<chain extends Chain | undefined>(client: Client<Transport, chain>): Promise<VaultDeltaHedgeFeeQuote>; //#endregion
|
|
100
|
+
export { MAX_VAULT_PRIORITY_FEE_PER_GAS, MAX_VAULT_TRANSACTION_GAS_COST, MIN_VAULT_PRIORITY_FEE_PER_GAS, VaultDeltaHedgeFeeQuote, VaultSignedTransactionFeeCaps, VaultSignedTransactionFeeValidationResult, VaultTransactionFeeEstimationError, VaultTransactionFeeQuote, VaultTransactionGasCostLimitError, VaultTransactionReplacementLimitError, applyVaultTransactionGasCostLimit, bufferVaultTransactionGasEstimate, getVaultDeltaHedgeHistoricalFeeQuote, getVaultDeltaHedgeInitialFeeQuote, getVaultTransactionFeeQuote, getVaultTransactionReplacementFeeQuote, validateVaultSignedTransactionFeeCaps };
|
|
63
101
|
//# sourceMappingURL=vault-transaction-fees.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vault-transaction-fees.d.ts","names":["Chain","Client","Transport","MIN_VAULT_PRIORITY_FEE_PER_GAS","MAX_VAULT_PRIORITY_FEE_PER_GAS","MAX_VAULT_TRANSACTION_GAS_COST","VaultTransactionFeeQuote","VaultSignedTransactionFeeCaps","VaultSignedTransactionFeeValidationResult","VaultTransactionFeeEstimationError","feeHistoryError","fallbackError","Error","VaultTransactionGasCostLimitError","gasLimit","maximumAffordableFeePerGas","minimumRequiredFeePerGas","FeeHistorySnapshot","FallbackFeeEstimate","resolveFeeHistoryQuote","baseFeePerGas","reward","resolveFallbackQuote","estimatedMaxFeePerGas","estimatedPriorityFeePerGas","applyVaultTransactionGasCostLimit","bufferVaultTransactionGasEstimate","validateVaultSignedTransactionFeeCaps","resolveVaultTransactionFeeQuote","readFeeHistory","readFallbackEstimate","Promise","getVaultTransactionFeeQuote","chain","__transactionFeeTestUtils"],"sources":["../src/hypoVault/transactionFees.d.ts"],"sourcesContent":null,"mappings":";;;cACqBG,8BAAAA;cACAC,8BAAAA;AADAD,cAEAE,8BAAAA,GAF8B,kBAAA;AAC9BD,KAETE,wBAAAA,GAFuC;EAC9BD,YAAAA,EAAAA,MAAAA;EACTC,oBAAAA,EAAAA,MAAwB;EAMxBC,mBAAAA,EAAAA,
|
|
1
|
+
{"version":3,"file":"vault-transaction-fees.d.ts","names":["Chain","Client","Transport","MIN_VAULT_PRIORITY_FEE_PER_GAS","MAX_VAULT_PRIORITY_FEE_PER_GAS","MAX_VAULT_TRANSACTION_GAS_COST","VaultTransactionFeeQuote","VaultDeltaHedgeFeeQuote","VaultSignedTransactionFeeCaps","VaultSignedTransactionFeeValidationResult","VaultTransactionFeeEstimationError","feeHistoryError","fallbackError","Error","VaultTransactionGasCostLimitError","gasLimit","maximumAffordableFeePerGas","minimumRequiredFeePerGas","VaultTransactionReplacementLimitError","code","requiredMaxFeePerGas","requiredMaxPriorityFeePerGas","FeeHistorySnapshot","FallbackFeeEstimate","clampPriorityFee","resolveFeeHistoryQuote","baseFeePerGas","reward","resolveDeltaHedgeFeeHistoryQuote","resolveRpcPriorityFeeQuote","rawPriorityFeePerGas","getVaultTransactionReplacementFeeQuote","originalQuote","historicalQuote","Pick","resolveFallbackQuote","estimatedMaxFeePerGas","estimatedPriorityFeePerGas","applyVaultTransactionGasCostLimit","bufferVaultTransactionGasEstimate","validateVaultSignedTransactionFeeCaps","resolveVaultTransactionFeeQuote","readFeeHistory","readFallbackEstimate","Promise","getVaultTransactionFeeQuote","chain","getVaultDeltaHedgeHistoricalFeeQuote","resolveVaultDeltaHedgeInitialFeeQuote","readRpcQuote","readHistoricalQuote","getVaultDeltaHedgeInitialFeeQuote","__transactionFeeTestUtils"],"sources":["../src/hypoVault/transactionFees.d.ts"],"sourcesContent":null,"mappings":";;;cACqBG,8BAAAA;cACAC,8BAAAA;AADAD,cAEAE,8BAAAA,GAF8B,kBAAA;AAC9BD,KAETE,wBAAAA,GAFuC;EAC9BD,YAAAA,EAAAA,MAAAA;EACTC,oBAAAA,EAAAA,MAAwB;EAMxBC,mBAAAA,EAAAA,MAAuB;EAGvBC,MAAAA,EAAAA,aAAAA,GAAAA,eAA6B,GAAA,kBAAA,GAAA,iBAAA;AAKzC,CAAA;AAOqBE,KAfTH,uBAAAA,GAA0BD,wBAeiB,GAAA;EAAA,oBAAA,EAAA,MAAA;CAAA;AAGpBM,KAfvBJ,6BAAAA,GAeuBI;EAAa,QAHgBC,CAAAA,EAAAA,MAAAA,GAAAA,IAAAA;EAAK,YAAA,EAAA,MAAA,GAAA,IAAA;EAQhDC,oBAAAA,EAAAA,MAAAA,GAAAA,IAAAA;CAAiC;AAIpCC,KAnBNN,yCAAAA,GAmBMM;EAAQ,KAAEC,EAAAA,IAAAA;CAA0B,GAAA;EAA0B,KAJjBH,EAAAA,KAAAA;EAAK,IAAA,EAAA,oBAAA,GAAA,gBAAA,GAAA,mBAAA,GAAA,oBAAA,GAAA,cAAA,GAAA,gBAAA;EAU/CK,MAAAA,EAAAA,MAAAA;CAAqC;AAKxCC,cAvBGT,kCAAAA,SAA2CG,KAAAA,CAuB9CM;EAAI,SAAEJ,eAAAA,EAAAA,OAAAA;EAAQ,SAAEK,aAAAA,EAAAA,OAAAA;EAAoB,WAAEC,CAAAA;IAAAA,eAAAA;IAAAA;EALgB,CAKhBA,EAAAA;IAA8BL,eAAAA,EAAAA,OAAAA;IALnBH,aAAAA,EAAAA,OAAAA;EAAK,CAAA;AA+BxE;AAA8D,cAzCzCC,iCAAAA,SAA0CD,KAAAA,CAyCD;EAAA,SAAGmB,QAAAA,EAAAA,MAAAA;EAAa,SAAEC,0BAAAA,EAAAA,MAAAA;EAAe,SAAElB,wBAAAA,EAAAA,MAAAA;EAAQ,WACjFT,CAAAA;IAAAA,QAAAA;IAAAA,0BAAAA;IAAAA;EAGG,CAHHA,EAAAA;IAAL4B,QAAAA,EAAAA,MAAAA;IACE3B,0BAAAA,EAAAA,MAAAA;IAEjBA,wBAAAA,EAAAA,MAAAA;EAAuB,CAAA;AAK3B;AAAyD,cAxCpCW,qCAAAA,SAA8CL,KAAAA,CAwCV;EAAA,SAAQP,IAAAA,EAAAA,oBAAAA;EAAwB,SAAqBA,oBAAAA,EAAAA,MAAAA;EAAwB,SAAA,4BAAA,EAAA,MAAA;EAC9GiC,SAAAA,0BAAAA,EAAiC,MAAA;EACjCC,WAAAA,CAAAA;IAAAA,IAAAA;IAAAA,QAAAA;IAAAA,oBAAqC;IAAA,4BAAA;IAAA;GAAA,EAAA;IAAA,IAAA,EAAA,oBAAA;IAAUhC,QAAAA,EAAAA,MAAAA;IAAuCF,oBAAAA,EAAAA,MAAAA;IAA2BG,4BAAAA,EAAAA,MAAAA;IAAyC,0BAAA,EAAA,MAAA;;;AAcrEP,iBAzBrF6B,sCAAAA,CAyBqF7B;EAAAA,aAAAA;EAAAA,eAAAA;EAAAA;CAAAA,EAAAA;EAAS,aAAE4C,EAxBrGZ,IAwBqGY,CAxBhGxC,wBAwBgGwC,EAAAA,cAAAA,GAAAA,sBAAAA,CAAAA;EAAK,eAAvB7C,EAvBjFM,uBAuBiFN;EAAM,QAA6BM,EAAAA,MAAAA;CAAuB,CAAA,EArB5JA,uBAqB6HqC;iBAhBzGN,iCAAAA,QAAyChC,6CAA6CA;iBACtFiC,iCAAAA;AA4BAY,iBA3BAX,qCAAAA,CA2BiC,OAAA,EA3BchC,6BA2Bd,EAAA,KAAA,CAAA,EA3BqDF,wBA2BrD,CAAA,EA3BgFG,yCA2BhF;;;;AAA4E;;;;;iBAd7GoC,0CAA0C7C,2BAA2BC,OAAOC,WAAW4C,SAASF,QAAQtC;iBACxGyC,mDAAmD/C,2BAA2BC,OAAOC,WAAW4C,SAASF,QAAQrC;;;;;;iBAajH4C,gDAAgDnD,2BAA2BC,OAAOC,WAAW4C,SAASF,QAAQrC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { hexToBigInt } from "viem";
|
|
2
|
+
import { estimateFeesPerGas, getBlock, getFeeHistory } from "viem/actions";
|
|
2
3
|
|
|
3
4
|
//#region src/hypoVault/transactionFees.ts
|
|
4
5
|
const MIN_VAULT_PRIORITY_FEE_PER_GAS = 100000000n;
|
|
@@ -6,8 +7,11 @@ const MAX_VAULT_PRIORITY_FEE_PER_GAS = 3000000000n;
|
|
|
6
7
|
const MAX_VAULT_TRANSACTION_GAS_COST = 15000000000000000n;
|
|
7
8
|
const FEE_HISTORY_BLOCK_COUNT = 20;
|
|
8
9
|
const FEE_HISTORY_REWARD_PERCENTILES = [90];
|
|
10
|
+
const DELTA_HEDGE_FEE_HISTORY_REWARD_PERCENTILES = [25];
|
|
9
11
|
const BASE_FEE_BUFFER_NUMERATOR = 1125n;
|
|
10
12
|
const BASE_FEE_BUFFER_DENOMINATOR = 1000n;
|
|
13
|
+
const REPLACEMENT_FEE_BUMP_NUMERATOR = 1125n;
|
|
14
|
+
const REPLACEMENT_FEE_BUMP_DENOMINATOR = 1000n;
|
|
11
15
|
const GAS_ESTIMATE_BUFFER_NUMERATOR = 3n;
|
|
12
16
|
const GAS_ESTIMATE_BUFFER_DENOMINATOR = 2n;
|
|
13
17
|
var VaultTransactionFeeEstimationError = class extends Error {
|
|
@@ -32,6 +36,20 @@ var VaultTransactionGasCostLimitError = class extends Error {
|
|
|
32
36
|
this.minimumRequiredFeePerGas = minimumRequiredFeePerGas;
|
|
33
37
|
}
|
|
34
38
|
};
|
|
39
|
+
var VaultTransactionReplacementLimitError = class extends Error {
|
|
40
|
+
code;
|
|
41
|
+
requiredMaxFeePerGas;
|
|
42
|
+
requiredMaxPriorityFeePerGas;
|
|
43
|
+
maximumAffordableFeePerGas;
|
|
44
|
+
constructor({ code, gasLimit, requiredMaxFeePerGas, requiredMaxPriorityFeePerGas, maximumAffordableFeePerGas }) {
|
|
45
|
+
super(`Vault transaction replacement blocked by ${code}: gasLimit=${gasLimit.toString()}, requiredMaxFeePerGas=${requiredMaxFeePerGas.toString()}, requiredMaxPriorityFeePerGas=${requiredMaxPriorityFeePerGas.toString()}, maximumAffordableFeePerGas=${maximumAffordableFeePerGas.toString()}`);
|
|
46
|
+
this.name = "VaultTransactionReplacementLimitError";
|
|
47
|
+
this.code = code;
|
|
48
|
+
this.requiredMaxFeePerGas = requiredMaxFeePerGas;
|
|
49
|
+
this.requiredMaxPriorityFeePerGas = requiredMaxPriorityFeePerGas;
|
|
50
|
+
this.maximumAffordableFeePerGas = maximumAffordableFeePerGas;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
35
53
|
function ceilMultiplyFraction(value, numerator, denominator) {
|
|
36
54
|
return (value * numerator + denominator - 1n) / denominator;
|
|
37
55
|
}
|
|
@@ -68,6 +86,57 @@ function resolveFeeHistoryQuote({ baseFeePerGas, reward }) {
|
|
|
68
86
|
source: "fee_history"
|
|
69
87
|
};
|
|
70
88
|
}
|
|
89
|
+
function resolveDeltaHedgeFeeHistoryQuote({ baseFeePerGas, reward }) {
|
|
90
|
+
const latestBaseFeeIndex = baseFeePerGas.length - 2;
|
|
91
|
+
if (latestBaseFeeIndex < 0 || reward === void 0 || reward.length === 0) return null;
|
|
92
|
+
const p25Rewards = reward.flatMap((blockRewards) => {
|
|
93
|
+
const p25 = blockRewards[0];
|
|
94
|
+
return p25 === void 0 ? [] : [p25];
|
|
95
|
+
});
|
|
96
|
+
const rawPriorityFeePerGas = medianBigInt(p25Rewards);
|
|
97
|
+
if (rawPriorityFeePerGas === void 0) return null;
|
|
98
|
+
const maxPriorityFeePerGas = clampPriorityFee(rawPriorityFeePerGas);
|
|
99
|
+
const bufferedBaseFee = ceilMultiplyFraction(baseFeePerGas[latestBaseFeeIndex], BASE_FEE_BUFFER_NUMERATOR, BASE_FEE_BUFFER_DENOMINATOR);
|
|
100
|
+
return {
|
|
101
|
+
maxFeePerGas: bufferedBaseFee + maxPriorityFeePerGas,
|
|
102
|
+
maxPriorityFeePerGas,
|
|
103
|
+
minimumMaxFeePerGas: bufferedBaseFee + MIN_VAULT_PRIORITY_FEE_PER_GAS,
|
|
104
|
+
rawPriorityFeePerGas,
|
|
105
|
+
source: "fee_history_p25"
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function resolveRpcPriorityFeeQuote({ baseFeePerGas, rawPriorityFeePerGas }) {
|
|
109
|
+
const bufferedBaseFee = ceilMultiplyFraction(baseFeePerGas, BASE_FEE_BUFFER_NUMERATOR, BASE_FEE_BUFFER_DENOMINATOR);
|
|
110
|
+
return {
|
|
111
|
+
maxFeePerGas: bufferedBaseFee + rawPriorityFeePerGas,
|
|
112
|
+
maxPriorityFeePerGas: rawPriorityFeePerGas,
|
|
113
|
+
minimumMaxFeePerGas: bufferedBaseFee + rawPriorityFeePerGas,
|
|
114
|
+
rawPriorityFeePerGas,
|
|
115
|
+
source: "rpc_priority_fee"
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function getVaultTransactionReplacementFeeQuote({ originalQuote, historicalQuote, gasLimit }) {
|
|
119
|
+
if (gasLimit <= 0n) throw new Error(`Vault transaction gas limit must be positive, received ${gasLimit.toString()}`);
|
|
120
|
+
const bumpedPriorityFee = ceilMultiplyFraction(originalQuote.maxPriorityFeePerGas, REPLACEMENT_FEE_BUMP_NUMERATOR, REPLACEMENT_FEE_BUMP_DENOMINATOR);
|
|
121
|
+
const bumpedMaxFee = ceilMultiplyFraction(originalQuote.maxFeePerGas, REPLACEMENT_FEE_BUMP_NUMERATOR, REPLACEMENT_FEE_BUMP_DENOMINATOR);
|
|
122
|
+
const requiredMaxPriorityFeePerGas = historicalQuote.maxPriorityFeePerGas > bumpedPriorityFee ? historicalQuote.maxPriorityFeePerGas : bumpedPriorityFee;
|
|
123
|
+
const bufferedBaseFee = historicalQuote.minimumMaxFeePerGas - MIN_VAULT_PRIORITY_FEE_PER_GAS;
|
|
124
|
+
const currentMarketMaxFee = bufferedBaseFee + requiredMaxPriorityFeePerGas;
|
|
125
|
+
const requiredMaxFeePerGas = currentMarketMaxFee > bumpedMaxFee ? currentMarketMaxFee : bumpedMaxFee;
|
|
126
|
+
const maximumAffordableFeePerGas = MAX_VAULT_TRANSACTION_GAS_COST / gasLimit;
|
|
127
|
+
if (requiredMaxFeePerGas > maximumAffordableFeePerGas) throw new VaultTransactionReplacementLimitError({
|
|
128
|
+
code: "GasCostCapExceeded",
|
|
129
|
+
gasLimit,
|
|
130
|
+
requiredMaxFeePerGas,
|
|
131
|
+
requiredMaxPriorityFeePerGas,
|
|
132
|
+
maximumAffordableFeePerGas
|
|
133
|
+
});
|
|
134
|
+
return {
|
|
135
|
+
...historicalQuote,
|
|
136
|
+
maxFeePerGas: requiredMaxFeePerGas,
|
|
137
|
+
maxPriorityFeePerGas: requiredMaxPriorityFeePerGas
|
|
138
|
+
};
|
|
139
|
+
}
|
|
71
140
|
function resolveFallbackQuote({ maxFeePerGas: estimatedMaxFeePerGas, maxPriorityFeePerGas: estimatedPriorityFeePerGas }) {
|
|
72
141
|
const maxPriorityFeePerGas = clampPriorityFee(estimatedPriorityFeePerGas);
|
|
73
142
|
const estimatedBaseFeeAllowance = estimatedMaxFeePerGas > estimatedPriorityFeePerGas ? estimatedMaxFeePerGas - estimatedPriorityFeePerGas : 0n;
|
|
@@ -169,7 +238,42 @@ async function getVaultTransactionFeeQuote(client) {
|
|
|
169
238
|
readFallbackEstimate: () => estimateFeesPerGas(client)
|
|
170
239
|
});
|
|
171
240
|
}
|
|
241
|
+
async function getVaultDeltaHedgeHistoricalFeeQuote(client) {
|
|
242
|
+
const feeHistory = await getFeeHistory(client, {
|
|
243
|
+
blockCount: FEE_HISTORY_BLOCK_COUNT,
|
|
244
|
+
blockTag: "latest",
|
|
245
|
+
rewardPercentiles: DELTA_HEDGE_FEE_HISTORY_REWARD_PERCENTILES
|
|
246
|
+
});
|
|
247
|
+
const quote = resolveDeltaHedgeFeeHistoryQuote(feeHistory);
|
|
248
|
+
if (quote === null) throw new Error("eth_feeHistory returned incomplete p25 base fee or reward data");
|
|
249
|
+
return quote;
|
|
250
|
+
}
|
|
251
|
+
async function resolveVaultDeltaHedgeInitialFeeQuote({ readRpcQuote, readHistoricalQuote }) {
|
|
252
|
+
try {
|
|
253
|
+
return resolveRpcPriorityFeeQuote(await readRpcQuote());
|
|
254
|
+
} catch {
|
|
255
|
+
return readHistoricalQuote();
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Resolve the first fee quote for a delta hedge from the connected RPC's
|
|
260
|
+
* eth_maxPriorityFeePerGas recommendation. A failed RPC recommendation falls
|
|
261
|
+
* back immediately to the rolling historical p25 quote.
|
|
262
|
+
*/
|
|
263
|
+
async function getVaultDeltaHedgeInitialFeeQuote(client) {
|
|
264
|
+
return resolveVaultDeltaHedgeInitialFeeQuote({
|
|
265
|
+
readRpcQuote: async () => {
|
|
266
|
+
const [rawPriorityFee, latestBlock] = await Promise.all([client.request({ method: "eth_maxPriorityFeePerGas" }), getBlock(client, { blockTag: "latest" })]);
|
|
267
|
+
if (latestBlock.baseFeePerGas === null) throw new Error("Latest block does not include an EIP-1559 base fee");
|
|
268
|
+
return {
|
|
269
|
+
baseFeePerGas: latestBlock.baseFeePerGas,
|
|
270
|
+
rawPriorityFeePerGas: hexToBigInt(rawPriorityFee)
|
|
271
|
+
};
|
|
272
|
+
},
|
|
273
|
+
readHistoricalQuote: () => getVaultDeltaHedgeHistoricalFeeQuote(client)
|
|
274
|
+
});
|
|
275
|
+
}
|
|
172
276
|
|
|
173
277
|
//#endregion
|
|
174
|
-
export { MAX_VAULT_PRIORITY_FEE_PER_GAS, MAX_VAULT_TRANSACTION_GAS_COST, MIN_VAULT_PRIORITY_FEE_PER_GAS, VaultTransactionFeeEstimationError, VaultTransactionGasCostLimitError, applyVaultTransactionGasCostLimit, bufferVaultTransactionGasEstimate, getVaultTransactionFeeQuote, validateVaultSignedTransactionFeeCaps };
|
|
278
|
+
export { MAX_VAULT_PRIORITY_FEE_PER_GAS, MAX_VAULT_TRANSACTION_GAS_COST, MIN_VAULT_PRIORITY_FEE_PER_GAS, VaultTransactionFeeEstimationError, VaultTransactionGasCostLimitError, VaultTransactionReplacementLimitError, applyVaultTransactionGasCostLimit, bufferVaultTransactionGasEstimate, getVaultDeltaHedgeHistoricalFeeQuote, getVaultDeltaHedgeInitialFeeQuote, getVaultTransactionFeeQuote, getVaultTransactionReplacementFeeQuote, validateVaultSignedTransactionFeeCaps };
|
|
175
279
|
//# sourceMappingURL=vault-transaction-fees.js.map
|