@panoptic-eng/sdk 1.0.32 → 1.0.34
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 +5 -5
- package/dist/cow/index.js +3 -3
- package/dist/cow/types.d.ts +2 -2
- package/dist/{cow-CLFJQ-OP.js → cow-aX6of9TS.js} +2 -2
- package/dist/{cow-CLFJQ-OP.js.map → cow-aX6of9TS.js.map} +1 -1
- package/dist/deployments.d.ts +25 -1
- package/dist/deployments.d.ts.map +1 -1
- package/dist/deployments.js +19 -1
- package/dist/deployments.js.map +1 -1
- package/dist/{index-DToj2-Vc.d.ts → index-CURXeKNy.d.ts} +412 -12
- package/dist/index-CURXeKNy.d.ts.map +1 -0
- package/dist/{index-DQS8Luef.d.ts → index-Cp-nCeV2.d.ts} +4 -4
- package/dist/{index-DQS8Luef.d.ts.map → index-Cp-nCeV2.d.ts.map} +1 -1
- package/dist/{index-CDCAju5o.d.ts → index-Zvu-rJpV.d.ts} +2 -2
- package/dist/{index-CDCAju5o.d.ts.map → index-Zvu-rJpV.d.ts.map} +1 -1
- package/dist/index.d.ts +384 -548
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1619 -1718
- package/dist/index.js.map +1 -1
- package/dist/{irm-BNtE1Dmg.d.ts → irm-CmgC1Mqi.d.ts} +3 -3
- package/dist/{irm-BNtE1Dmg.d.ts.map → irm-CmgC1Mqi.d.ts.map} +1 -1
- package/dist/{irm-iAI9hTYQ.js → irm-DnM96-X4.js} +342 -3
- package/dist/irm-DnM96-X4.js.map +1 -0
- package/dist/panoptic/v2/greeks/index.d.ts +2 -2
- package/dist/panoptic/v2/index.d.ts +8 -8
- package/dist/panoptic/v2/index.js +6 -5
- package/dist/panoptic/v2/react-public.d.ts +13 -13
- package/dist/panoptic/v2/react-public.d.ts.map +1 -1
- package/dist/panoptic/v2/react-public.js +10 -9
- package/dist/panoptic/v2/react-public.js.map +1 -1
- package/dist/{position-Bmd_3nzI.d.ts → position-BqIgubs5.d.ts} +1 -1
- package/dist/{position-Bmd_3nzI.d.ts.map → position-BqIgubs5.d.ts.map} +1 -1
- package/dist/{position-ClU7GrTa.js → position-C8rkkKhi.js} +10 -4
- package/dist/{position-ClU7GrTa.js.map → position-C8rkkKhi.js.map} +1 -1
- package/dist/{oracle-DaNTHk7B.d.ts → quote-BxQkPBRg.d.ts} +57 -4
- package/dist/quote-BxQkPBRg.d.ts.map +1 -0
- package/dist/{router-DKFR_vnu.js → router-CS86ptMu.js} +6 -87
- package/dist/router-CS86ptMu.js.map +1 -0
- package/dist/router-DcoU2KmV.js +313 -0
- package/dist/router-DcoU2KmV.js.map +1 -0
- package/dist/{simulation-CUqERC5Y.d.ts → simulation-zM6-YUaw.d.ts} +2 -2
- package/dist/{simulation-CUqERC5Y.d.ts.map → simulation-zM6-YUaw.d.ts.map} +1 -1
- package/dist/{tx-BXXqhBHn.d.ts → tx-CbDQ58Io.d.ts} +1 -1
- package/dist/{tx-BXXqhBHn.d.ts.map → tx-CbDQ58Io.d.ts.map} +1 -1
- package/dist/{types-DgWfno7q.d.ts → types-BHdnurYr.d.ts} +2 -2
- package/dist/{types-DgWfno7q.d.ts.map → types-BHdnurYr.d.ts.map} +1 -1
- package/dist/{types-Cy6v8iPf.d.ts → types-D_jcYss-.d.ts} +5 -4
- package/dist/types-D_jcYss-.d.ts.map +1 -0
- package/dist/uniswap/index.d.ts +53 -100
- package/dist/uniswap/index.d.ts.map +1 -1
- package/dist/uniswap/index.js +4 -226
- package/dist/uniswap/index.js.map +1 -1
- package/dist/{v2-DHJxPCAp.js → v2-D0dEatKb.js} +841 -65
- package/dist/v2-D0dEatKb.js.map +1 -0
- package/dist/{writes-DQLGdkJ5.js → writes-AupZCK4M.js} +2 -2
- package/dist/{writes-DQLGdkJ5.js.map → writes-AupZCK4M.js.map} +1 -1
- package/dist/zodiac/index.d.ts +74 -1
- package/dist/zodiac/index.d.ts.map +1 -1
- package/dist/zodiac/index.js +213 -3
- package/dist/zodiac/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/index-DToj2-Vc.d.ts.map +0 -1
- package/dist/irm-iAI9hTYQ.js.map +0 -1
- package/dist/oracle-DaNTHk7B.d.ts.map +0 -1
- package/dist/router-DKFR_vnu.js.map +0 -1
- package/dist/types-Cy6v8iPf.d.ts.map +0 -1
- package/dist/v2-DHJxPCAp.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { formatTokenAmount$1 as formatTokenAmount, getAccountCollateral$1 as getAccountCollateral, panopticQueryAbi, parseTokenAmount$1 as parseTokenAmount, readBlockAndAggregate, requireReturnData } from "./irm-
|
|
2
|
-
import { AccountInsolventError$1 as AccountInsolventError, ChunkLimitError$1 as ChunkLimitError, DEFAULT_VEGOID$1 as DEFAULT_VEGOID, InvalidHistoryRangeError$1 as InvalidHistoryRangeError, NotEnoughTokensError$1 as NotEnoughTokensError, PanopticError, PanopticValidationError$1 as PanopticValidationError, StorageDataNotFoundError, collateralTrackerV2Abi, decodeLeftRightSigned$1 as decodeLeftRightSigned, decodeLeftRightUnsigned$1 as decodeLeftRightUnsigned, decodePosition, decodePositionBalance, decodeTickSpacing$1 as decodeTickSpacing, getBlockMeta$1 as getBlockMeta, getPool, panopticFactoryV3Abi, panopticFactoryV4Abi, panopticGuardianAbi, panopticPoolV2Abi, panopticQueryAbi$1, parsePanopticError$1 as parsePanopticError, riskEngineAbi, semiFungiblePositionManagerV3Abi, semiFungiblePositionManagerV4Abi, stateViewAbi, uniswapV3PoolAbi } from "./position-
|
|
1
|
+
import { StateViewAbi, formatTokenAmount$1 as formatTokenAmount, getAccountCollateral$1 as getAccountCollateral, panopticQueryAbi, parseTokenAmount$1 as parseTokenAmount, readBlockAndAggregate, requireReturnData } from "./irm-DnM96-X4.js";
|
|
2
|
+
import { AccountInsolventError$1 as AccountInsolventError, ChunkLimitError$1 as ChunkLimitError, DEFAULT_VEGOID$1 as DEFAULT_VEGOID, InvalidHistoryRangeError$1 as InvalidHistoryRangeError, NotEnoughTokensError$1 as NotEnoughTokensError, PanopticError, PanopticValidationError$1 as PanopticValidationError, StorageDataNotFoundError, WrongUniswapPoolError$1 as WrongUniswapPoolError, collateralTrackerV2Abi, decodeLeftRightSigned$1 as decodeLeftRightSigned, decodeLeftRightUnsigned$1 as decodeLeftRightUnsigned, decodePosition, decodePositionBalance, decodeTickSpacing$1 as decodeTickSpacing, getBlockMeta$1 as getBlockMeta, getPool, panopticFactoryV3Abi, panopticFactoryV4Abi, panopticGuardianAbi, panopticPoolV2Abi, panopticQueryAbi$1, parsePanopticError$1 as parsePanopticError, riskEngineAbi, semiFungiblePositionManagerV3Abi, semiFungiblePositionManagerV4Abi, stateViewAbi, uniswapV3PoolAbi } from "./position-C8rkkKhi.js";
|
|
3
3
|
import { MAX_TICK, MAX_TRACKED_CHUNKS, MIN_TICK, WAD, calculatePositionDelta, calculatePositionGamma, calculatePositionValue, priceToTick, sqrtPriceX96ToTick, tickLimits, tickToPrice, tickToPriceDecimalScaled, tickToSqrtPriceX96 } from "./greeks-GysWXct-.js";
|
|
4
|
-
import { addLegToTokenId$1 as addLegToTokenId, buildBatchDispatchArgs$1 as buildBatchDispatchArgs, buildUniqueCredit$1 as buildUniqueCredit, countLegs$1 as countLegs, decodeAllLegs$1 as decodeAllLegs, decodeTokenId$1 as decodeTokenId, getClosedPositionsKey$1 as getClosedPositionsKey, getPendingPositionsKey$1 as getPendingPositionsKey, getPoolMetaKey$1 as getPoolMetaKey, getPositionMetaKey$1 as getPositionMetaKey, getPositionsKey$1 as getPositionsKey, getTrackedChunksKey$1 as getTrackedChunksKey, getTrackedPositionIds$1 as getTrackedPositionIds, jsonSerializer$1 as jsonSerializer, loadCheckpoint$1 as loadCheckpoint, resolveTokenIndex$1 as resolveTokenIndex, simulateOpenPosition$1 as simulateOpenPosition, simulateWithTokenFlow } from "./writes-
|
|
5
|
-
import { ContractFunctionExecutionError, decodeFunctionResult, encodeAbiParameters, encodeFunctionData, getAddress, keccak256, zeroAddress } from "viem";
|
|
4
|
+
import { addLegToTokenId$1 as addLegToTokenId, buildBatchDispatchArgs$1 as buildBatchDispatchArgs, buildUniqueCredit$1 as buildUniqueCredit, countLegs$1 as countLegs, createTokenIdBuilder$1 as createTokenIdBuilder, decodeAllLegs$1 as decodeAllLegs, decodeTokenId$1 as decodeTokenId, getClosedPositionsKey$1 as getClosedPositionsKey, getPendingPositionsKey$1 as getPendingPositionsKey, getPoolMetaKey$1 as getPoolMetaKey, getPositionMetaKey$1 as getPositionMetaKey, getPositionsKey$1 as getPositionsKey, getTrackedChunksKey$1 as getTrackedChunksKey, getTrackedPositionIds$1 as getTrackedPositionIds, jsonSerializer$1 as jsonSerializer, loadCheckpoint$1 as loadCheckpoint, resolveTokenIndex$1 as resolveTokenIndex, simulateOpenPosition$1 as simulateOpenPosition, simulateWithTokenFlow } from "./writes-AupZCK4M.js";
|
|
5
|
+
import { BaseError, ContractFunctionExecutionError, ContractFunctionRevertedError, ExecutionRevertedError, decodeFunctionResult, encodeAbiParameters, encodeFunctionData, getAddress, keccak256, toHex, zeroAddress } from "viem";
|
|
6
6
|
import { multicall } from "viem/actions";
|
|
7
7
|
|
|
8
8
|
//#region src/panoptic/v2/clients/blocksByTimestamp.ts
|
|
@@ -203,6 +203,277 @@ 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/sfpmSwap/calldata.ts
|
|
208
|
+
/**
|
|
209
|
+
* Encode the `multicall([mint, burn])` for a swap plan.
|
|
210
|
+
*
|
|
211
|
+
* The order is always `[mint, burn]` — the ERC1155 must be minted before it is
|
|
212
|
+
* burned. Which call carries the inverted (swap) limits is decided in the plan.
|
|
213
|
+
*/
|
|
214
|
+
function buildSfpmSwapCalldata(plan) {
|
|
215
|
+
const mintData = encodeFunctionData({
|
|
216
|
+
abi: semiFungiblePositionManagerV3Abi,
|
|
217
|
+
functionName: "mintTokenizedPosition",
|
|
218
|
+
args: [
|
|
219
|
+
plan.poolKey,
|
|
220
|
+
plan.tokenId,
|
|
221
|
+
plan.positionSize,
|
|
222
|
+
plan.mintTickLimits[0],
|
|
223
|
+
plan.mintTickLimits[1]
|
|
224
|
+
]
|
|
225
|
+
});
|
|
226
|
+
const burnData = encodeFunctionData({
|
|
227
|
+
abi: semiFungiblePositionManagerV3Abi,
|
|
228
|
+
functionName: "burnTokenizedPosition",
|
|
229
|
+
args: [
|
|
230
|
+
plan.poolKey,
|
|
231
|
+
plan.tokenId,
|
|
232
|
+
plan.positionSize,
|
|
233
|
+
plan.burnTickLimits[0],
|
|
234
|
+
plan.burnTickLimits[1]
|
|
235
|
+
]
|
|
236
|
+
});
|
|
237
|
+
const multicallData = encodeFunctionData({
|
|
238
|
+
abi: semiFungiblePositionManagerV3Abi,
|
|
239
|
+
functionName: "multicall",
|
|
240
|
+
args: [[mintData, burnData]]
|
|
241
|
+
});
|
|
242
|
+
return {
|
|
243
|
+
multicallData,
|
|
244
|
+
mintData,
|
|
245
|
+
burnData
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
//#endregion
|
|
250
|
+
//#region src/panoptic/v2/sfpmSwap/init.ts
|
|
251
|
+
/**
|
|
252
|
+
* Resolve the `uint64` SFPM poolId for a Uniswap v3 pool, initializing it if needed.
|
|
253
|
+
*
|
|
254
|
+
* `initializeAMMPool` is permissionless and idempotent and **returns the poolId**
|
|
255
|
+
* whether or not the pool was already registered, so a `simulateContract` call is
|
|
256
|
+
* enough to learn the id without sending a transaction. Always resolve the id this
|
|
257
|
+
* way rather than encoding it offline — the SFPM can collision-increment ids.
|
|
258
|
+
*/
|
|
259
|
+
async function fetchSfpmV3PoolId(params) {
|
|
260
|
+
const { client, sfpmAddress, token0, token1, fee } = params;
|
|
261
|
+
const vegoid = params.vegoid ?? Number(DEFAULT_VEGOID);
|
|
262
|
+
const { result } = await client.simulateContract({
|
|
263
|
+
address: sfpmAddress,
|
|
264
|
+
abi: semiFungiblePositionManagerV3Abi,
|
|
265
|
+
functionName: "initializeAMMPool",
|
|
266
|
+
args: [
|
|
267
|
+
token0,
|
|
268
|
+
token1,
|
|
269
|
+
fee,
|
|
270
|
+
vegoid
|
|
271
|
+
]
|
|
272
|
+
});
|
|
273
|
+
return BigInt(result);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Ensure a Uniswap v3 pool is registered on the SFPM, sending `initializeAMMPool`
|
|
277
|
+
* only if it is not already registered. Returns the resolved poolId.
|
|
278
|
+
*
|
|
279
|
+
* When `expectedPool` is given, the resolved id is checked to map back to it via
|
|
280
|
+
* `getUniswapV3PoolFromId` — guards against a wrong token/fee triple.
|
|
281
|
+
*/
|
|
282
|
+
async function ensureSfpmV3PoolInitialized(params) {
|
|
283
|
+
const { client, wallet, sfpmAddress, token0, token1, fee, expectedPool } = params;
|
|
284
|
+
const vegoid = params.vegoid ?? Number(DEFAULT_VEGOID);
|
|
285
|
+
const poolId = await fetchSfpmV3PoolId({
|
|
286
|
+
client,
|
|
287
|
+
sfpmAddress,
|
|
288
|
+
token0,
|
|
289
|
+
token1,
|
|
290
|
+
fee,
|
|
291
|
+
vegoid
|
|
292
|
+
});
|
|
293
|
+
const registered = await client.readContract({
|
|
294
|
+
address: sfpmAddress,
|
|
295
|
+
abi: semiFungiblePositionManagerV3Abi,
|
|
296
|
+
functionName: "getUniswapV3PoolFromId",
|
|
297
|
+
args: [poolId]
|
|
298
|
+
});
|
|
299
|
+
let initialized = false;
|
|
300
|
+
let resolved = registered;
|
|
301
|
+
if (getAddress(registered) === zeroAddress) {
|
|
302
|
+
const account = wallet.account;
|
|
303
|
+
if (account === void 0) throw new PanopticError("wallet client has no account");
|
|
304
|
+
const hash = await wallet.writeContract({
|
|
305
|
+
account,
|
|
306
|
+
chain: wallet.chain ?? null,
|
|
307
|
+
address: sfpmAddress,
|
|
308
|
+
abi: semiFungiblePositionManagerV3Abi,
|
|
309
|
+
functionName: "initializeAMMPool",
|
|
310
|
+
args: [
|
|
311
|
+
token0,
|
|
312
|
+
token1,
|
|
313
|
+
fee,
|
|
314
|
+
vegoid
|
|
315
|
+
]
|
|
316
|
+
});
|
|
317
|
+
await client.waitForTransactionReceipt({ hash });
|
|
318
|
+
initialized = true;
|
|
319
|
+
resolved = await client.readContract({
|
|
320
|
+
address: sfpmAddress,
|
|
321
|
+
abi: semiFungiblePositionManagerV3Abi,
|
|
322
|
+
functionName: "getUniswapV3PoolFromId",
|
|
323
|
+
args: [poolId]
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
if (expectedPool !== void 0 && getAddress(resolved) !== getAddress(expectedPool)) throw new WrongUniswapPoolError(new PanopticError(`SFPM poolId ${poolId} resolves to ${resolved}, expected ${expectedPool}`));
|
|
327
|
+
return {
|
|
328
|
+
poolId,
|
|
329
|
+
initialized
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
//#endregion
|
|
334
|
+
//#region src/panoptic/v2/sfpmSwap/plan.ts
|
|
335
|
+
/** Wide, non-inverted band for the paired (non-swapping) call — never triggers a swap. */
|
|
336
|
+
const WIDE_LIMITS = [Number(MIN_TICK) + 1, Number(MAX_TICK) - 1];
|
|
337
|
+
/**
|
|
338
|
+
* Convert a slippage tolerance in bps to a conservative Uniswap tick distance.
|
|
339
|
+
*
|
|
340
|
+
* Ticks are 1.0001^tick, so each tick ≈ 1 bps. This walks up powers of 1.0001
|
|
341
|
+
* until the cumulative price move covers `slippageBps`, matching the hedger-bot's
|
|
342
|
+
* dispatch-path helper so both swap paths agree on band width.
|
|
343
|
+
*/
|
|
344
|
+
function slippageBpsToTickDistance(slippageBps) {
|
|
345
|
+
if (slippageBps < 0n || slippageBps > 1000n) throw new PanopticError(`slippage bps ${slippageBps} out of bounds (0..1000)`);
|
|
346
|
+
if (slippageBps === 0n) return 0n;
|
|
347
|
+
let numerator = 1n;
|
|
348
|
+
let denominator = 1n;
|
|
349
|
+
let ticks = 0n;
|
|
350
|
+
while (numerator * 10000n < denominator * (10000n + slippageBps)) {
|
|
351
|
+
numerator *= 10001n;
|
|
352
|
+
denominator *= 10000n;
|
|
353
|
+
ticks += 1n;
|
|
354
|
+
}
|
|
355
|
+
return ticks;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Build the swap plan.
|
|
359
|
+
*
|
|
360
|
+
* Mechanism (verified in the Phase 0 fork test):
|
|
361
|
+
* - A single-leg **loan** tokenId (width=0, isLong=false, `asset == tokenType`) moves
|
|
362
|
+
* exactly `positionSize` of the `tokenType` token when its call carries inverted
|
|
363
|
+
* tick limits (`low > high`); the paired call uses a wide band and moves nothing.
|
|
364
|
+
* - `exactIn`: swap on the **mint**; `tokenType` = the **input** token index.
|
|
365
|
+
* - `exactOut`: swap on the **burn** (isLong flips → exact-output); `tokenType` = the
|
|
366
|
+
* **output** token index.
|
|
367
|
+
*
|
|
368
|
+
* The inverted band is centered on `currentTick` at ±`slippageBpsToTickDistance`,
|
|
369
|
+
* which the SFPM re-sorts and enforces as an open interval on the post-swap tick.
|
|
370
|
+
*/
|
|
371
|
+
function buildSfpmSwapPlan(params) {
|
|
372
|
+
const { sfpmAddress, poolAddress, poolId, kind, zeroForOne, amount, currentTick, slippageBps } = params;
|
|
373
|
+
if (amount <= 0n) throw new PanopticError(`swap amount must be positive (got ${amount})`);
|
|
374
|
+
const distance = slippageBpsToTickDistance(slippageBps);
|
|
375
|
+
if (distance < 1n) throw new PanopticError(`slippageBps ${slippageBps} yields a zero-width tick band; use a larger tolerance`);
|
|
376
|
+
const tokenType = kind === "exactIn" ? zeroForOne ? 0n : 1n : zeroForOne ? 1n : 0n;
|
|
377
|
+
const tokenId = createTokenIdBuilder(poolId).addLoan({
|
|
378
|
+
asset: tokenType,
|
|
379
|
+
tokenType,
|
|
380
|
+
strike: 0n
|
|
381
|
+
}).build();
|
|
382
|
+
const d = Number(distance);
|
|
383
|
+
const low = Math.min(Number(MAX_TICK), currentTick + d);
|
|
384
|
+
const high = Math.max(Number(MIN_TICK), currentTick - d);
|
|
385
|
+
if (low <= high) throw new PanopticError(`slippageBps ${slippageBps} at tick ${currentTick} yields a non-inverted band after clamping`);
|
|
386
|
+
const invertedLimits = [low, high];
|
|
387
|
+
const swapOn = kind === "exactIn" ? "mint" : "burn";
|
|
388
|
+
return {
|
|
389
|
+
sfpmAddress,
|
|
390
|
+
poolAddress,
|
|
391
|
+
poolKey: encodeAbiParameters([{ type: "address" }], [poolAddress]),
|
|
392
|
+
tokenId,
|
|
393
|
+
positionSize: amount,
|
|
394
|
+
mintTickLimits: swapOn === "mint" ? invertedLimits : WIDE_LIMITS,
|
|
395
|
+
burnTickLimits: swapOn === "burn" ? invertedLimits : WIDE_LIMITS,
|
|
396
|
+
swapOn,
|
|
397
|
+
kind
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
//#endregion
|
|
402
|
+
//#region src/panoptic/v2/sfpmSwap/quote.ts
|
|
403
|
+
const UINT128 = 1n << 128n;
|
|
404
|
+
const INT128_MAX = (1n << 127n) - 1n;
|
|
405
|
+
/** Extract the two signed 128-bit slots from a packed `LeftRightSigned` int256. */
|
|
406
|
+
function unpackLeftRightSigned(packed) {
|
|
407
|
+
const u = packed < 0n ? packed + (1n << 256n) : packed;
|
|
408
|
+
const toInt128 = (half) => half > INT128_MAX ? half - UINT128 : half;
|
|
409
|
+
return {
|
|
410
|
+
right: toInt128(u & UINT128 - 1n),
|
|
411
|
+
left: toInt128(u >> 128n & UINT128 - 1n)
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
/** Wrap an unknown thrown value as a PanopticError, decoding Panoptic reverts when possible. */
|
|
415
|
+
function toPanopticError(err) {
|
|
416
|
+
if (err instanceof PanopticError) return err;
|
|
417
|
+
const parsed = parsePanopticError(err);
|
|
418
|
+
if (parsed) return parsed.error;
|
|
419
|
+
return new PanopticError(err instanceof Error ? err.message : "SFPM swap simulation failed", err instanceof Error ? err : void 0);
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Quote a swap by simulating `SFPM.multicall([mint, burn])` and decoding the swap
|
|
423
|
+
* call's `totalMoved` return. Authoritative — captures the width-0 loan-leg wei
|
|
424
|
+
* rounding a raw QuoterV2 quote would miss.
|
|
425
|
+
*/
|
|
426
|
+
async function quoteSfpmSwap(params) {
|
|
427
|
+
const { client, plan, account, stateOverride, blockNumber } = params;
|
|
428
|
+
const { mintData, burnData } = buildSfpmSwapCalldata(plan);
|
|
429
|
+
const _meta = await getBlockMeta({
|
|
430
|
+
client,
|
|
431
|
+
blockNumber
|
|
432
|
+
});
|
|
433
|
+
try {
|
|
434
|
+
const { result } = await client.simulateContract({
|
|
435
|
+
account,
|
|
436
|
+
address: plan.sfpmAddress,
|
|
437
|
+
abi: semiFungiblePositionManagerV3Abi,
|
|
438
|
+
functionName: "multicall",
|
|
439
|
+
args: [[mintData, burnData]],
|
|
440
|
+
blockNumber,
|
|
441
|
+
stateOverride
|
|
442
|
+
});
|
|
443
|
+
const swapIndex = plan.swapOn === "mint" ? 0 : 1;
|
|
444
|
+
const decoded = decodeFunctionResult({
|
|
445
|
+
abi: semiFungiblePositionManagerV3Abi,
|
|
446
|
+
functionName: plan.swapOn === "mint" ? "mintTokenizedPosition" : "burnTokenizedPosition",
|
|
447
|
+
data: result[swapIndex]
|
|
448
|
+
});
|
|
449
|
+
const finalTick = Number(decoded[2]);
|
|
450
|
+
const { right, left } = unpackLeftRightSigned(decoded[1]);
|
|
451
|
+
const inSlot = [right, left].find((s) => s > 0n);
|
|
452
|
+
const outSlot = [right, left].find((s) => s < 0n);
|
|
453
|
+
if (inSlot === void 0 || outSlot === void 0) return {
|
|
454
|
+
success: false,
|
|
455
|
+
error: new PanopticError(`SFPM swap simulation moved no tokens (totalMoved=${decoded[1]})`),
|
|
456
|
+
_meta
|
|
457
|
+
};
|
|
458
|
+
return {
|
|
459
|
+
success: true,
|
|
460
|
+
data: {
|
|
461
|
+
amountIn: inSlot,
|
|
462
|
+
amountOut: -outSlot,
|
|
463
|
+
finalTick
|
|
464
|
+
},
|
|
465
|
+
gasEstimate: 0n,
|
|
466
|
+
_meta
|
|
467
|
+
};
|
|
468
|
+
} catch (err) {
|
|
469
|
+
return {
|
|
470
|
+
success: false,
|
|
471
|
+
error: toPanopticError(err),
|
|
472
|
+
_meta
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
206
477
|
//#endregion
|
|
207
478
|
//#region src/panoptic/v2/reads/sfpm.ts
|
|
208
479
|
/**
|
|
@@ -1477,8 +1748,8 @@ async function createFlowNeutralTokenId(params) {
|
|
|
1477
1748
|
if (tickBefore === null) throw new PanopticError("Cannot create flow-neutral position: current tick unavailable");
|
|
1478
1749
|
const sqrtPX96 = tickToSqrtPriceX96(tickBefore);
|
|
1479
1750
|
const valueAbs = (index, amount) => {
|
|
1480
|
-
const abs = amount < 0n ? -amount : amount;
|
|
1481
|
-
return index === 0n ? abs * sqrtPX96 * sqrtPX96 / Q192$1 : abs;
|
|
1751
|
+
const abs$1 = amount < 0n ? -amount : amount;
|
|
1752
|
+
return index === 0n ? abs$1 * sqrtPX96 * sqrtPX96 / Q192$1 : abs$1;
|
|
1482
1753
|
};
|
|
1483
1754
|
const flowFor = (index) => index === 0n ? credit.creditAmount0 : credit.creditAmount1;
|
|
1484
1755
|
if (queryAddress !== void 0) {
|
|
@@ -2877,7 +3148,7 @@ function calculateAccountGreeksPure(params) {
|
|
|
2877
3148
|
const MIN_TICK$1 = -887272n;
|
|
2878
3149
|
const MAX_TICK$1 = 887272n;
|
|
2879
3150
|
const FP96 = 1n << 96n;
|
|
2880
|
-
const Q128$
|
|
3151
|
+
const Q128$3 = 1n << 128n;
|
|
2881
3152
|
/** Cap for a usage ratio with no collateral behind it. */
|
|
2882
3153
|
const MAX_USAGE_BPS = 1000000n;
|
|
2883
3154
|
const bigintMax = (a, b) => a > b ? a : b;
|
|
@@ -2895,16 +3166,16 @@ const MINT_BUFFER_DENOMINATOR = 10000000n;
|
|
|
2895
3166
|
* Matches the on-chain `PanopticMath.convert0to1` truncation, with an
|
|
2896
3167
|
* overflow-safe branch when `sqrtPriceX96^2` would not fit in uint256.
|
|
2897
3168
|
*/
|
|
2898
|
-
function convert0to1$
|
|
2899
|
-
if (sqrtPriceX96 < Q128$
|
|
3169
|
+
function convert0to1$2(amount, sqrtPriceX96) {
|
|
3170
|
+
if (sqrtPriceX96 < Q128$3) return amount * sqrtPriceX96 * sqrtPriceX96 >> 192n;
|
|
2900
3171
|
const sp2Hi = sqrtPriceX96 * sqrtPriceX96 >> 64n;
|
|
2901
3172
|
return amount * sp2Hi >> 128n;
|
|
2902
3173
|
}
|
|
2903
3174
|
/**
|
|
2904
3175
|
* Convert a token1 amount to its token0-equivalent at the given sqrtPriceX96.
|
|
2905
3176
|
*/
|
|
2906
|
-
function convert1to0$
|
|
2907
|
-
if (sqrtPriceX96 < Q128$
|
|
3177
|
+
function convert1to0$2(amount, sqrtPriceX96) {
|
|
3178
|
+
if (sqrtPriceX96 < Q128$3) {
|
|
2908
3179
|
const denom = sqrtPriceX96 * sqrtPriceX96;
|
|
2909
3180
|
return amount * (1n << 192n) / denom;
|
|
2910
3181
|
}
|
|
@@ -3084,10 +3355,10 @@ async function getMarginBuffer(params) {
|
|
|
3084
3355
|
}
|
|
3085
3356
|
const sqrtPriceX96 = tickToSqrtPriceX96(currentTick);
|
|
3086
3357
|
const denominatedInToken = sqrtPriceX96 < FP96 ? 0 : 1;
|
|
3087
|
-
const currentMargin0 = assets0 + convert1to0$
|
|
3088
|
-
const requiredMargin0 = required0Native + convert1to0$
|
|
3089
|
-
const currentMargin1 = assets1 + convert0to1$
|
|
3090
|
-
const requiredMargin1 = required1Native + convert0to1$
|
|
3358
|
+
const currentMargin0 = assets0 + convert1to0$2(assets1, sqrtPriceX96);
|
|
3359
|
+
const requiredMargin0 = required0Native + convert1to0$2(required1Native, sqrtPriceX96);
|
|
3360
|
+
const currentMargin1 = assets1 + convert0to1$2(assets0, sqrtPriceX96);
|
|
3361
|
+
const requiredMargin1 = required1Native + convert0to1$2(required0Native, sqrtPriceX96);
|
|
3091
3362
|
const buffer0 = currentMargin0 - requiredMargin0;
|
|
3092
3363
|
const buffer1 = currentMargin1 - requiredMargin1;
|
|
3093
3364
|
const bufferPercent0 = requiredMargin0 === 0n ? null : buffer0 * 10000n / requiredMargin0;
|
|
@@ -3363,14 +3634,14 @@ async function getCollateralTotalAssetsBatch(client, collateralTrackerAddresses,
|
|
|
3363
3634
|
|
|
3364
3635
|
//#endregion
|
|
3365
3636
|
//#region src/panoptic/v2/reads/buyingPower.ts
|
|
3366
|
-
const Q128 = 1n << 128n;
|
|
3367
|
-
function convert0to1(amount, sqrtPriceX96) {
|
|
3368
|
-
if (sqrtPriceX96 < Q128) return amount * sqrtPriceX96 * sqrtPriceX96 >> 192n;
|
|
3637
|
+
const Q128$2 = 1n << 128n;
|
|
3638
|
+
function convert0to1$1(amount, sqrtPriceX96) {
|
|
3639
|
+
if (sqrtPriceX96 < Q128$2) return amount * sqrtPriceX96 * sqrtPriceX96 >> 192n;
|
|
3369
3640
|
const sp2Hi = sqrtPriceX96 * sqrtPriceX96 >> 64n;
|
|
3370
3641
|
return amount * sp2Hi >> 128n;
|
|
3371
3642
|
}
|
|
3372
|
-
function convert1to0(amount, sqrtPriceX96) {
|
|
3373
|
-
if (sqrtPriceX96 < Q128) {
|
|
3643
|
+
function convert1to0$1(amount, sqrtPriceX96) {
|
|
3644
|
+
if (sqrtPriceX96 < Q128$2) {
|
|
3374
3645
|
const denom = sqrtPriceX96 * sqrtPriceX96;
|
|
3375
3646
|
return amount * (1n << 192n) / denom;
|
|
3376
3647
|
}
|
|
@@ -3491,10 +3762,10 @@ async function getAccountBuyingPower(params) {
|
|
|
3491
3762
|
}
|
|
3492
3763
|
}
|
|
3493
3764
|
const sqrtPriceX96 = tickToSqrtPriceX96(currentTick);
|
|
3494
|
-
const collateralBalance0 = assets0 + convert1to0(assets1, sqrtPriceX96);
|
|
3495
|
-
const requiredCollateral0 = required0Native + convert1to0(required1Native, sqrtPriceX96);
|
|
3496
|
-
const collateralBalance1 = assets1 + convert0to1(assets0, sqrtPriceX96);
|
|
3497
|
-
const requiredCollateral1 = required1Native + convert0to1(required0Native, sqrtPriceX96);
|
|
3765
|
+
const collateralBalance0 = assets0 + convert1to0$1(assets1, sqrtPriceX96);
|
|
3766
|
+
const requiredCollateral0 = required0Native + convert1to0$1(required1Native, sqrtPriceX96);
|
|
3767
|
+
const collateralBalance1 = assets1 + convert0to1$1(assets0, sqrtPriceX96);
|
|
3768
|
+
const requiredCollateral1 = required1Native + convert0to1$1(required0Native, sqrtPriceX96);
|
|
3498
3769
|
return {
|
|
3499
3770
|
collateralBalance0,
|
|
3500
3771
|
requiredCollateral0,
|
|
@@ -3504,6 +3775,68 @@ async function getAccountBuyingPower(params) {
|
|
|
3504
3775
|
};
|
|
3505
3776
|
}
|
|
3506
3777
|
|
|
3778
|
+
//#endregion
|
|
3779
|
+
//#region src/panoptic/v2/simulations/creditWrap.ts
|
|
3780
|
+
/**
|
|
3781
|
+
* Wrap a dispatch with a temporary credit leg that is opened and closed in the
|
|
3782
|
+
* same transaction, netting to a swap.
|
|
3783
|
+
*
|
|
3784
|
+
* `swapAtMint` is not a calldata flag — it is the ORDER of the tick-limit pair:
|
|
3785
|
+
* descending `[high, low]` turns the swap on, ascending `[low, high]` leaves it
|
|
3786
|
+
* off. Exactly one of the two legs carries it, and which one is what makes the
|
|
3787
|
+
* swap exact-in vs exact-out.
|
|
3788
|
+
*/
|
|
3789
|
+
function buildCreditWrappedDispatch(params) {
|
|
3790
|
+
const { dispatch, creditTokenId, creditPositionSize, direction, placement } = params;
|
|
3791
|
+
const low = params.tickLimitLow <= params.tickLimitHigh ? params.tickLimitLow : params.tickLimitHigh;
|
|
3792
|
+
const high = params.tickLimitLow <= params.tickLimitHigh ? params.tickLimitHigh : params.tickLimitLow;
|
|
3793
|
+
const swapping = [
|
|
3794
|
+
high,
|
|
3795
|
+
low,
|
|
3796
|
+
0n
|
|
3797
|
+
];
|
|
3798
|
+
const notSwapping = [
|
|
3799
|
+
low,
|
|
3800
|
+
high,
|
|
3801
|
+
0n
|
|
3802
|
+
];
|
|
3803
|
+
const mintLimits = direction === "exact-out" ? swapping : notSwapping;
|
|
3804
|
+
const burnLimits = direction === "exact-out" ? notSwapping : swapping;
|
|
3805
|
+
const wrapped = {
|
|
3806
|
+
positionIdList: placement === "straddle" ? [
|
|
3807
|
+
creditTokenId,
|
|
3808
|
+
...dispatch.positionIdList,
|
|
3809
|
+
creditTokenId
|
|
3810
|
+
] : [
|
|
3811
|
+
...dispatch.positionIdList,
|
|
3812
|
+
creditTokenId,
|
|
3813
|
+
creditTokenId
|
|
3814
|
+
],
|
|
3815
|
+
finalPositionIdList: [...dispatch.finalPositionIdList],
|
|
3816
|
+
positionSizes: placement === "straddle" ? [
|
|
3817
|
+
creditPositionSize,
|
|
3818
|
+
...dispatch.positionSizes,
|
|
3819
|
+
0n
|
|
3820
|
+
] : [
|
|
3821
|
+
...dispatch.positionSizes,
|
|
3822
|
+
creditPositionSize,
|
|
3823
|
+
0n
|
|
3824
|
+
],
|
|
3825
|
+
tickAndSpreadLimits: placement === "straddle" ? [
|
|
3826
|
+
mintLimits,
|
|
3827
|
+
...dispatch.tickAndSpreadLimits,
|
|
3828
|
+
burnLimits
|
|
3829
|
+
] : [
|
|
3830
|
+
...dispatch.tickAndSpreadLimits,
|
|
3831
|
+
mintLimits,
|
|
3832
|
+
burnLimits
|
|
3833
|
+
],
|
|
3834
|
+
usePremiaAsCollateral: dispatch.usePremiaAsCollateral,
|
|
3835
|
+
builderCode: dispatch.builderCode
|
|
3836
|
+
};
|
|
3837
|
+
return wrapped;
|
|
3838
|
+
}
|
|
3839
|
+
|
|
3507
3840
|
//#endregion
|
|
3508
3841
|
//#region src/panoptic/v2/simulations/simulateDispatch.ts
|
|
3509
3842
|
/**
|
|
@@ -3629,7 +3962,7 @@ async function simulateDispatch(params) {
|
|
|
3629
3962
|
|
|
3630
3963
|
//#endregion
|
|
3631
3964
|
//#region src/panoptic/v2/simulations/tokenShortfallRecovery.ts
|
|
3632
|
-
const BPS_DENOMINATOR = 10000n;
|
|
3965
|
+
const BPS_DENOMINATOR$1 = 10000n;
|
|
3633
3966
|
const MAX_RECOVERY_QUOTE_ATTEMPTS = 8;
|
|
3634
3967
|
/**
|
|
3635
3968
|
* Wrap a dispatch with a temporary credit leg that sources the shortfall.
|
|
@@ -3642,39 +3975,11 @@ const MAX_RECOVERY_QUOTE_ATTEMPTS = 8;
|
|
|
3642
3975
|
* token's utilization — the case that fails today on a >94% utilized tracker.
|
|
3643
3976
|
*/
|
|
3644
3977
|
function buildTokenShortfallRecoveryDispatch(params) {
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
low,
|
|
3651
|
-
0n
|
|
3652
|
-
];
|
|
3653
|
-
const burnLimits = [
|
|
3654
|
-
low,
|
|
3655
|
-
high,
|
|
3656
|
-
0n
|
|
3657
|
-
];
|
|
3658
|
-
return {
|
|
3659
|
-
positionIdList: [
|
|
3660
|
-
creditTokenId,
|
|
3661
|
-
...dispatch.positionIdList,
|
|
3662
|
-
creditTokenId
|
|
3663
|
-
],
|
|
3664
|
-
finalPositionIdList: [...dispatch.finalPositionIdList],
|
|
3665
|
-
positionSizes: [
|
|
3666
|
-
creditPositionSize,
|
|
3667
|
-
...dispatch.positionSizes,
|
|
3668
|
-
0n
|
|
3669
|
-
],
|
|
3670
|
-
tickAndSpreadLimits: [
|
|
3671
|
-
mintLimits,
|
|
3672
|
-
...dispatch.tickAndSpreadLimits,
|
|
3673
|
-
burnLimits
|
|
3674
|
-
],
|
|
3675
|
-
usePremiaAsCollateral: dispatch.usePremiaAsCollateral,
|
|
3676
|
-
builderCode: dispatch.builderCode
|
|
3677
|
-
};
|
|
3978
|
+
return buildCreditWrappedDispatch({
|
|
3979
|
+
...params,
|
|
3980
|
+
direction: "exact-out",
|
|
3981
|
+
placement: "straddle"
|
|
3982
|
+
});
|
|
3678
3983
|
}
|
|
3679
3984
|
/**
|
|
3680
3985
|
* Extract a fully-decoded `NotEnoughTokens` revert from an arbitrary error.
|
|
@@ -3697,7 +4002,7 @@ function getNotEnoughTokensError(error) {
|
|
|
3697
4002
|
}
|
|
3698
4003
|
function maximumAmountIn(estimatedAmountIn, slippageBps) {
|
|
3699
4004
|
if (slippageBps < 0n) throw new PanopticError("slippageBps must be non-negative");
|
|
3700
|
-
return (estimatedAmountIn * (BPS_DENOMINATOR + slippageBps) + BPS_DENOMINATOR - 1n) / BPS_DENOMINATOR;
|
|
4005
|
+
return (estimatedAmountIn * (BPS_DENOMINATOR$1 + slippageBps) + BPS_DENOMINATOR$1 - 1n) / BPS_DENOMINATOR$1;
|
|
3701
4006
|
}
|
|
3702
4007
|
function getInputAmount(tokenFlow, tokenInIndex) {
|
|
3703
4008
|
const delta = tokenInIndex === 0n ? tokenFlow.delta0 : tokenFlow.delta1;
|
|
@@ -3722,10 +4027,10 @@ async function quoteTokenShortfallRecovery(params) {
|
|
|
3722
4027
|
reason: "invalid-shortfall",
|
|
3723
4028
|
detail: `requested=${shortfallError.assetsRequested} <= balance=${shortfallError.assetBalance}`
|
|
3724
4029
|
};
|
|
3725
|
-
if (params.slippageBps < 0n || params.slippageBps > BPS_DENOMINATOR) return {
|
|
4030
|
+
if (params.slippageBps < 0n || params.slippageBps > BPS_DENOMINATOR$1) return {
|
|
3726
4031
|
available: false,
|
|
3727
4032
|
reason: "invalid-slippage",
|
|
3728
|
-
detail: `slippageBps=${params.slippageBps} is outside [0, ${BPS_DENOMINATOR}]`
|
|
4033
|
+
detail: `slippageBps=${params.slippageBps} is outside [0, ${BPS_DENOMINATOR$1}]`
|
|
3729
4034
|
};
|
|
3730
4035
|
const tickLimitLow = params.tickLimitLow ?? MIN_TICK;
|
|
3731
4036
|
const tickLimitHigh = params.tickLimitHigh ?? MAX_TICK;
|
|
@@ -4059,7 +4364,14 @@ async function getUniswapFeeHistory(params) {
|
|
|
4059
4364
|
_meta: _meta$1
|
|
4060
4365
|
};
|
|
4061
4366
|
}
|
|
4062
|
-
const [blockData, _meta] = await Promise.all([
|
|
4367
|
+
const [blockData, blockMetadata, _meta] = await Promise.all([
|
|
4368
|
+
fetchUniswapFeeData(client, blockNumbers, legs, poolConfig),
|
|
4369
|
+
Promise.all(blockNumbers.map((blockNumber) => getBlockMeta({
|
|
4370
|
+
client,
|
|
4371
|
+
blockNumber
|
|
4372
|
+
}))),
|
|
4373
|
+
params._meta ? Promise.resolve(params._meta) : getBlockMeta({ client })
|
|
4374
|
+
]);
|
|
4063
4375
|
let initialFees0 = null;
|
|
4064
4376
|
let initialFees1 = null;
|
|
4065
4377
|
const snapshots = blockData.map((bd, i) => {
|
|
@@ -4069,7 +4381,8 @@ async function getUniswapFeeHistory(params) {
|
|
|
4069
4381
|
initialFees1 = total1;
|
|
4070
4382
|
}
|
|
4071
4383
|
return {
|
|
4072
|
-
blockNumber:
|
|
4384
|
+
blockNumber: blockMetadata[i].blockNumber,
|
|
4385
|
+
blockTimestamp: blockMetadata[i].blockTimestamp,
|
|
4073
4386
|
fees: {
|
|
4074
4387
|
token0: total0 - initialFees0,
|
|
4075
4388
|
token1: total1 - initialFees1
|
|
@@ -4668,6 +4981,224 @@ async function getUniswapV4PoolLiquidities(params) {
|
|
|
4668
4981
|
};
|
|
4669
4982
|
}
|
|
4670
4983
|
|
|
4984
|
+
//#endregion
|
|
4985
|
+
//#region src/panoptic/v2/reads/uniswapLpPosition.ts
|
|
4986
|
+
const nfpmAbi = [{
|
|
4987
|
+
type: "function",
|
|
4988
|
+
name: "positions",
|
|
4989
|
+
inputs: [{
|
|
4990
|
+
name: "tokenId",
|
|
4991
|
+
type: "uint256"
|
|
4992
|
+
}],
|
|
4993
|
+
outputs: [
|
|
4994
|
+
{
|
|
4995
|
+
name: "nonce",
|
|
4996
|
+
type: "uint96"
|
|
4997
|
+
},
|
|
4998
|
+
{
|
|
4999
|
+
name: "operator",
|
|
5000
|
+
type: "address"
|
|
5001
|
+
},
|
|
5002
|
+
{
|
|
5003
|
+
name: "token0",
|
|
5004
|
+
type: "address"
|
|
5005
|
+
},
|
|
5006
|
+
{
|
|
5007
|
+
name: "token1",
|
|
5008
|
+
type: "address"
|
|
5009
|
+
},
|
|
5010
|
+
{
|
|
5011
|
+
name: "fee",
|
|
5012
|
+
type: "uint24"
|
|
5013
|
+
},
|
|
5014
|
+
{
|
|
5015
|
+
name: "tickLower",
|
|
5016
|
+
type: "int24"
|
|
5017
|
+
},
|
|
5018
|
+
{
|
|
5019
|
+
name: "tickUpper",
|
|
5020
|
+
type: "int24"
|
|
5021
|
+
},
|
|
5022
|
+
{
|
|
5023
|
+
name: "liquidity",
|
|
5024
|
+
type: "uint128"
|
|
5025
|
+
},
|
|
5026
|
+
{
|
|
5027
|
+
name: "feeGrowthInside0LastX128",
|
|
5028
|
+
type: "uint256"
|
|
5029
|
+
},
|
|
5030
|
+
{
|
|
5031
|
+
name: "feeGrowthInside1LastX128",
|
|
5032
|
+
type: "uint256"
|
|
5033
|
+
},
|
|
5034
|
+
{
|
|
5035
|
+
name: "tokensOwed0",
|
|
5036
|
+
type: "uint128"
|
|
5037
|
+
},
|
|
5038
|
+
{
|
|
5039
|
+
name: "tokensOwed1",
|
|
5040
|
+
type: "uint128"
|
|
5041
|
+
}
|
|
5042
|
+
],
|
|
5043
|
+
stateMutability: "view"
|
|
5044
|
+
}, {
|
|
5045
|
+
type: "function",
|
|
5046
|
+
name: "collect",
|
|
5047
|
+
inputs: [{
|
|
5048
|
+
name: "params",
|
|
5049
|
+
type: "tuple",
|
|
5050
|
+
components: [
|
|
5051
|
+
{
|
|
5052
|
+
name: "tokenId",
|
|
5053
|
+
type: "uint256"
|
|
5054
|
+
},
|
|
5055
|
+
{
|
|
5056
|
+
name: "recipient",
|
|
5057
|
+
type: "address"
|
|
5058
|
+
},
|
|
5059
|
+
{
|
|
5060
|
+
name: "amount0Max",
|
|
5061
|
+
type: "uint128"
|
|
5062
|
+
},
|
|
5063
|
+
{
|
|
5064
|
+
name: "amount1Max",
|
|
5065
|
+
type: "uint128"
|
|
5066
|
+
}
|
|
5067
|
+
]
|
|
5068
|
+
}],
|
|
5069
|
+
outputs: [{
|
|
5070
|
+
name: "amount0",
|
|
5071
|
+
type: "uint256"
|
|
5072
|
+
}, {
|
|
5073
|
+
name: "amount1",
|
|
5074
|
+
type: "uint256"
|
|
5075
|
+
}],
|
|
5076
|
+
stateMutability: "payable"
|
|
5077
|
+
}];
|
|
5078
|
+
const MAX_UINT128 = 2n ** 128n - 1n;
|
|
5079
|
+
const MAX_UINT256 = 2n ** 256n - 1n;
|
|
5080
|
+
const Q128$1 = 2n ** 128n;
|
|
5081
|
+
/**
|
|
5082
|
+
* Whether an error thrown by a viem contract call is an on-chain revert (as
|
|
5083
|
+
* opposed to a transport/RPC failure such as a timeout or rate limit).
|
|
5084
|
+
*/
|
|
5085
|
+
function isContractRevert(error) {
|
|
5086
|
+
return error instanceof BaseError && error.walk((err) => err instanceof ContractFunctionRevertedError || err instanceof ExecutionRevertedError) != null;
|
|
5087
|
+
}
|
|
5088
|
+
/**
|
|
5089
|
+
* Fetch a Uniswap V3 LP position's state and uncollected fees.
|
|
5090
|
+
*
|
|
5091
|
+
* Fees come from simulating `collect` with max amounts as the owner — one
|
|
5092
|
+
* eth_call returning the exact claimable amounts (tokensOwed + fee growth
|
|
5093
|
+
* since the last poke). The simulation is best-effort: if it reverts (e.g.
|
|
5094
|
+
* an empty position), fees fall back to 0.
|
|
5095
|
+
*/
|
|
5096
|
+
async function getUniswapV3LpPositionState(params) {
|
|
5097
|
+
const { client, nfpmAddress, tokenId, owner, blockNumber } = params;
|
|
5098
|
+
const _meta = await getBlockMeta({
|
|
5099
|
+
client,
|
|
5100
|
+
blockNumber
|
|
5101
|
+
});
|
|
5102
|
+
const position = await client.readContract({
|
|
5103
|
+
address: nfpmAddress,
|
|
5104
|
+
abi: nfpmAbi,
|
|
5105
|
+
functionName: "positions",
|
|
5106
|
+
args: [tokenId],
|
|
5107
|
+
blockNumber: _meta.blockNumber
|
|
5108
|
+
});
|
|
5109
|
+
const [, , token0, token1, fee, tickLower, tickUpper, liquidity] = position;
|
|
5110
|
+
let fees0 = 0n;
|
|
5111
|
+
let fees1 = 0n;
|
|
5112
|
+
try {
|
|
5113
|
+
const { result } = await client.simulateContract({
|
|
5114
|
+
address: nfpmAddress,
|
|
5115
|
+
abi: nfpmAbi,
|
|
5116
|
+
functionName: "collect",
|
|
5117
|
+
args: [{
|
|
5118
|
+
tokenId,
|
|
5119
|
+
recipient: owner,
|
|
5120
|
+
amount0Max: MAX_UINT128,
|
|
5121
|
+
amount1Max: MAX_UINT128
|
|
5122
|
+
}],
|
|
5123
|
+
account: owner,
|
|
5124
|
+
blockNumber: _meta.blockNumber
|
|
5125
|
+
});
|
|
5126
|
+
[fees0, fees1] = result;
|
|
5127
|
+
} catch (error) {
|
|
5128
|
+
if (!isContractRevert(error)) throw error;
|
|
5129
|
+
}
|
|
5130
|
+
return {
|
|
5131
|
+
token0,
|
|
5132
|
+
token1,
|
|
5133
|
+
fee: Number(fee),
|
|
5134
|
+
tickLower: Number(tickLower),
|
|
5135
|
+
tickUpper: Number(tickUpper),
|
|
5136
|
+
liquidity,
|
|
5137
|
+
fees0,
|
|
5138
|
+
fees1,
|
|
5139
|
+
_meta
|
|
5140
|
+
};
|
|
5141
|
+
}
|
|
5142
|
+
/**
|
|
5143
|
+
* Uncollected fees from a feeGrowthInside delta, mirroring v4-core's
|
|
5144
|
+
* `Position.calculatePositionFeesAccrued`: the subtraction wraps around
|
|
5145
|
+
* uint256 (feeGrowthInside can legitimately underflow in-protocol).
|
|
5146
|
+
*/
|
|
5147
|
+
function feesFromFeeGrowthDelta(feeGrowthInsideCurrentX128, feeGrowthInsideLastX128, liquidity) {
|
|
5148
|
+
const delta = feeGrowthInsideCurrentX128 - feeGrowthInsideLastX128 & MAX_UINT256;
|
|
5149
|
+
return delta * liquidity / Q128$1;
|
|
5150
|
+
}
|
|
5151
|
+
/**
|
|
5152
|
+
* Fetch a Uniswap V4 LP position's state and uncollected fees via StateView.
|
|
5153
|
+
*
|
|
5154
|
+
* The position inside PoolManager is keyed by (positionManager, tickLower,
|
|
5155
|
+
* tickUpper, salt) where posm uses `bytes32(tokenId)` as the salt. Fees on
|
|
5156
|
+
* pools with fee-taking hooks may be approximate.
|
|
5157
|
+
*/
|
|
5158
|
+
async function getUniswapV4LpPositionState(params) {
|
|
5159
|
+
const { client, stateViewAddress, positionManagerAddress, poolId, tokenId, tickLower, tickUpper, blockNumber } = params;
|
|
5160
|
+
const salt = toHex(tokenId, { size: 32 });
|
|
5161
|
+
const _meta = await getBlockMeta({
|
|
5162
|
+
client,
|
|
5163
|
+
blockNumber
|
|
5164
|
+
});
|
|
5165
|
+
const [positionInfo, feeGrowthInside] = await client.multicall({
|
|
5166
|
+
allowFailure: false,
|
|
5167
|
+
blockNumber: _meta.blockNumber,
|
|
5168
|
+
contracts: [{
|
|
5169
|
+
address: stateViewAddress,
|
|
5170
|
+
abi: StateViewAbi,
|
|
5171
|
+
functionName: "getPositionInfo",
|
|
5172
|
+
args: [
|
|
5173
|
+
poolId,
|
|
5174
|
+
positionManagerAddress,
|
|
5175
|
+
tickLower,
|
|
5176
|
+
tickUpper,
|
|
5177
|
+
salt
|
|
5178
|
+
]
|
|
5179
|
+
}, {
|
|
5180
|
+
address: stateViewAddress,
|
|
5181
|
+
abi: StateViewAbi,
|
|
5182
|
+
functionName: "getFeeGrowthInside",
|
|
5183
|
+
args: [
|
|
5184
|
+
poolId,
|
|
5185
|
+
tickLower,
|
|
5186
|
+
tickUpper
|
|
5187
|
+
]
|
|
5188
|
+
}]
|
|
5189
|
+
});
|
|
5190
|
+
const [liquidity, feeGrowthInside0LastX128, feeGrowthInside1LastX128] = positionInfo;
|
|
5191
|
+
const [feeGrowthInside0X128, feeGrowthInside1X128] = feeGrowthInside;
|
|
5192
|
+
return {
|
|
5193
|
+
liquidity,
|
|
5194
|
+
tickLower,
|
|
5195
|
+
tickUpper,
|
|
5196
|
+
fees0: feesFromFeeGrowthDelta(feeGrowthInside0X128, feeGrowthInside0LastX128, liquidity),
|
|
5197
|
+
fees1: feesFromFeeGrowthDelta(feeGrowthInside1X128, feeGrowthInside1LastX128, liquidity),
|
|
5198
|
+
_meta
|
|
5199
|
+
};
|
|
5200
|
+
}
|
|
5201
|
+
|
|
4671
5202
|
//#endregion
|
|
4672
5203
|
//#region src/panoptic/v2/reads/priceHistory.ts
|
|
4673
5204
|
/**
|
|
@@ -6598,6 +7129,251 @@ async function simulateSwapExactIn(params) {
|
|
|
6598
7129
|
}
|
|
6599
7130
|
}
|
|
6600
7131
|
|
|
7132
|
+
//#endregion
|
|
7133
|
+
//#region src/panoptic/v2/utils/priceConvert.ts
|
|
7134
|
+
const Q128 = 1n << 128n;
|
|
7135
|
+
/**
|
|
7136
|
+
* A non-positive price has no meaningful conversion, and `convert1to0` would
|
|
7137
|
+
* divide by zero — surface that as a typed SDK error rather than a RangeError
|
|
7138
|
+
* thrown from inside the arithmetic.
|
|
7139
|
+
*/
|
|
7140
|
+
function assertPositivePrice(sqrtPriceX96) {
|
|
7141
|
+
if (sqrtPriceX96 <= 0n) throw new PanopticError(`sqrtPriceX96 must be positive, got ${sqrtPriceX96}`);
|
|
7142
|
+
}
|
|
7143
|
+
/** Convert a token0 amount to its token1-equivalent at the given sqrtPriceX96. */
|
|
7144
|
+
function convert0to1(amount, sqrtPriceX96) {
|
|
7145
|
+
assertPositivePrice(sqrtPriceX96);
|
|
7146
|
+
if (sqrtPriceX96 < Q128) return amount * sqrtPriceX96 * sqrtPriceX96 >> 192n;
|
|
7147
|
+
const sp2Hi = sqrtPriceX96 * sqrtPriceX96 >> 64n;
|
|
7148
|
+
return amount * sp2Hi >> 128n;
|
|
7149
|
+
}
|
|
7150
|
+
/** Convert a token1 amount to its token0-equivalent at the given sqrtPriceX96. */
|
|
7151
|
+
function convert1to0(amount, sqrtPriceX96) {
|
|
7152
|
+
assertPositivePrice(sqrtPriceX96);
|
|
7153
|
+
if (sqrtPriceX96 < Q128) {
|
|
7154
|
+
const denom = sqrtPriceX96 * sqrtPriceX96;
|
|
7155
|
+
return amount * (1n << 192n) / denom;
|
|
7156
|
+
}
|
|
7157
|
+
const sp2Hi = sqrtPriceX96 * sqrtPriceX96 >> 64n;
|
|
7158
|
+
return amount * (1n << 128n) / sp2Hi;
|
|
7159
|
+
}
|
|
7160
|
+
/**
|
|
7161
|
+
* Convert an amount denominated in `fromTokenIndex` into the other token's
|
|
7162
|
+
* terms, so the two sides of a pool flow can be compared on one scale.
|
|
7163
|
+
*/
|
|
7164
|
+
function convertToTokenIndex(amount, fromTokenIndex, toTokenIndex, sqrtPriceX96) {
|
|
7165
|
+
if (fromTokenIndex === toTokenIndex) return amount;
|
|
7166
|
+
return fromTokenIndex === 0n ? convert0to1(amount, sqrtPriceX96) : convert1to0(amount, sqrtPriceX96);
|
|
7167
|
+
}
|
|
7168
|
+
|
|
7169
|
+
//#endregion
|
|
7170
|
+
//#region src/panoptic/v2/simulations/oneTokenFlow.ts
|
|
7171
|
+
const BPS_DENOMINATOR = 10000n;
|
|
7172
|
+
/**
|
|
7173
|
+
* Default {@link OneTokenFlowQuoteParams.minSwapRatioBps}: 0.5%.
|
|
7174
|
+
*
|
|
7175
|
+
* A swap pays a pool fee of roughly 5-30 bps plus slippage, so a non-target
|
|
7176
|
+
* flow below this fraction of the target flow cannot pay for itself — while
|
|
7177
|
+
* still leaving any residual small enough not to surprise someone who asked to
|
|
7178
|
+
* settle in one token.
|
|
7179
|
+
*/
|
|
7180
|
+
const DEFAULT_MIN_SWAP_RATIO_BPS = 50n;
|
|
7181
|
+
function deltaAt(tokenFlow, index) {
|
|
7182
|
+
return index === 0n ? tokenFlow.delta0 : tokenFlow.delta1;
|
|
7183
|
+
}
|
|
7184
|
+
function balanceBeforeAt(tokenFlow, index) {
|
|
7185
|
+
return index === 0n ? tokenFlow.balanceBefore0 : tokenFlow.balanceBefore1;
|
|
7186
|
+
}
|
|
7187
|
+
function abs(value) {
|
|
7188
|
+
return value < 0n ? -value : value;
|
|
7189
|
+
}
|
|
7190
|
+
function padForSlippage(amount, slippageBps) {
|
|
7191
|
+
return (amount * (BPS_DENOMINATOR + slippageBps) + BPS_DENOMINATOR - 1n) / BPS_DENOMINATOR;
|
|
7192
|
+
}
|
|
7193
|
+
/**
|
|
7194
|
+
* Quote a dispatch wrapped so its net flow lands in `targetTokenIndex` only.
|
|
7195
|
+
*
|
|
7196
|
+
* Three simulations, all pinned to one block and with no convergence loop:
|
|
7197
|
+
*
|
|
7198
|
+
* 1. the user's dispatch as-is, to measure the non-target flow to cancel;
|
|
7199
|
+
* 2. the credit legs alone, to price the swap and check the source balance;
|
|
7200
|
+
* 3. the wrapped dispatch, whose token flow is what the user is shown and what
|
|
7201
|
+
* the residual dust is read from.
|
|
7202
|
+
*/
|
|
7203
|
+
async function quoteOneTokenFlow(params) {
|
|
7204
|
+
const { targetTokenIndex } = params;
|
|
7205
|
+
const minSwapRatioBps = params.minSwapRatioBps ?? DEFAULT_MIN_SWAP_RATIO_BPS;
|
|
7206
|
+
if (targetTokenIndex !== 0n && targetTokenIndex !== 1n) return {
|
|
7207
|
+
available: false,
|
|
7208
|
+
reason: "invalid-target-token",
|
|
7209
|
+
detail: `targetTokenIndex=${targetTokenIndex} is neither 0 nor 1`
|
|
7210
|
+
};
|
|
7211
|
+
if (params.slippageBps < 0n || params.slippageBps > BPS_DENOMINATOR) return {
|
|
7212
|
+
available: false,
|
|
7213
|
+
reason: "invalid-slippage",
|
|
7214
|
+
detail: `slippageBps=${params.slippageBps} is outside [0, ${BPS_DENOMINATOR}]`
|
|
7215
|
+
};
|
|
7216
|
+
const tickLimitLow = params.tickLimitLow ?? MIN_TICK;
|
|
7217
|
+
const tickLimitHigh = params.tickLimitHigh ?? MAX_TICK;
|
|
7218
|
+
if (tickLimitLow >= tickLimitHigh) return {
|
|
7219
|
+
available: false,
|
|
7220
|
+
reason: "invalid-tick-limits",
|
|
7221
|
+
detail: `tickLimitLow=${tickLimitLow} >= tickLimitHigh=${tickLimitHigh}`
|
|
7222
|
+
};
|
|
7223
|
+
const otherTokenIndex = targetTokenIndex === 0n ? 1n : 0n;
|
|
7224
|
+
const targetBlockNumber = params.blockNumber ?? await params.client.getBlockNumber();
|
|
7225
|
+
const simulateArgs = {
|
|
7226
|
+
client: params.client,
|
|
7227
|
+
poolAddress: params.poolAddress,
|
|
7228
|
+
account: params.account,
|
|
7229
|
+
existingPositionIdList: params.existingPositionIds,
|
|
7230
|
+
blockNumber: targetBlockNumber
|
|
7231
|
+
};
|
|
7232
|
+
const pool = await getPool({
|
|
7233
|
+
client: params.client,
|
|
7234
|
+
poolAddress: params.poolAddress,
|
|
7235
|
+
chainId: params.chainId,
|
|
7236
|
+
blockNumber: targetBlockNumber
|
|
7237
|
+
});
|
|
7238
|
+
const token0 = pool.collateralTracker0.token;
|
|
7239
|
+
const token1 = pool.collateralTracker1.token;
|
|
7240
|
+
const targetToken = targetTokenIndex === 0n ? token0 : token1;
|
|
7241
|
+
const otherToken = otherTokenIndex === 0n ? token0 : token1;
|
|
7242
|
+
const otherTracker = otherTokenIndex === 0n ? pool.collateralTracker0.address : pool.collateralTracker1.address;
|
|
7243
|
+
const baseSimulation = await simulateDispatch({
|
|
7244
|
+
...simulateArgs,
|
|
7245
|
+
...params.dispatch
|
|
7246
|
+
});
|
|
7247
|
+
let swapAmount;
|
|
7248
|
+
let direction;
|
|
7249
|
+
let baseTargetDelta = null;
|
|
7250
|
+
if (baseSimulation.success && baseSimulation.tokenFlow !== void 0) {
|
|
7251
|
+
baseTargetDelta = deltaAt(baseSimulation.tokenFlow, targetTokenIndex);
|
|
7252
|
+
const otherDelta = deltaAt(baseSimulation.tokenFlow, otherTokenIndex);
|
|
7253
|
+
if (otherDelta === 0n) return {
|
|
7254
|
+
available: false,
|
|
7255
|
+
reason: "already-single-token",
|
|
7256
|
+
detail: "the dispatch does not move the non-target token"
|
|
7257
|
+
};
|
|
7258
|
+
direction = otherDelta < 0n ? "exact-out" : "exact-in";
|
|
7259
|
+
swapAmount = abs(otherDelta);
|
|
7260
|
+
} else {
|
|
7261
|
+
const shortfall = baseSimulation.success ? null : getNotEnoughTokensError(baseSimulation.error);
|
|
7262
|
+
if (shortfall === null) return {
|
|
7263
|
+
available: false,
|
|
7264
|
+
reason: "base-simulation-failed",
|
|
7265
|
+
detail: baseSimulation.success ? "base simulation returned no token flow" : `base simulation reverted: ${baseSimulation.error.message}`,
|
|
7266
|
+
error: baseSimulation.success ? void 0 : baseSimulation.error
|
|
7267
|
+
};
|
|
7268
|
+
if (shortfall.tokenAddress.toLowerCase() !== otherTracker.toLowerCase()) return {
|
|
7269
|
+
available: false,
|
|
7270
|
+
reason: "base-simulation-failed",
|
|
7271
|
+
detail: `shortfall is in ${shortfall.tokenAddress}, not the non-target collateral ${otherTracker}`,
|
|
7272
|
+
error: baseSimulation.success ? void 0 : baseSimulation.error
|
|
7273
|
+
};
|
|
7274
|
+
const pending = shortfall.assetsRequested - shortfall.assetBalance;
|
|
7275
|
+
if (pending <= 0n) return {
|
|
7276
|
+
available: false,
|
|
7277
|
+
reason: "base-simulation-failed",
|
|
7278
|
+
detail: `requested=${shortfall.assetsRequested} <= balance=${shortfall.assetBalance}`
|
|
7279
|
+
};
|
|
7280
|
+
direction = "exact-out";
|
|
7281
|
+
swapAmount = pending;
|
|
7282
|
+
}
|
|
7283
|
+
if (baseTargetDelta !== null && minSwapRatioBps > 0n) {
|
|
7284
|
+
const swapInTargetTerms = convertToTokenIndex(swapAmount, otherTokenIndex, targetTokenIndex, pool.sqrtPriceX96);
|
|
7285
|
+
if (swapInTargetTerms * BPS_DENOMINATOR < minSwapRatioBps * abs(baseTargetDelta)) return {
|
|
7286
|
+
available: false,
|
|
7287
|
+
reason: "below-threshold",
|
|
7288
|
+
detail: `non-target flow ${swapInTargetTerms} (in target token terms) is below ${minSwapRatioBps}bps of the target flow ${abs(baseTargetDelta)}`
|
|
7289
|
+
};
|
|
7290
|
+
}
|
|
7291
|
+
const collisionIds = Array.from(new Set([
|
|
7292
|
+
...params.existingPositionIds,
|
|
7293
|
+
...params.dispatch.positionIdList,
|
|
7294
|
+
...params.dispatch.finalPositionIdList
|
|
7295
|
+
]));
|
|
7296
|
+
const credit = buildUniqueCredit(pool.poolId, otherTokenIndex, otherTokenIndex, pool.currentTick, pool.tickSpacing, collisionIds, swapAmount);
|
|
7297
|
+
const placement = direction === "exact-out" ? "straddle" : "append";
|
|
7298
|
+
const creditWrapArgs = {
|
|
7299
|
+
creditTokenId: credit.tokenId,
|
|
7300
|
+
creditPositionSize: credit.adjustedSize,
|
|
7301
|
+
tickLimitLow,
|
|
7302
|
+
tickLimitHigh,
|
|
7303
|
+
direction,
|
|
7304
|
+
placement
|
|
7305
|
+
};
|
|
7306
|
+
let estimatedCounterAmount = 0n;
|
|
7307
|
+
let maximumAmountIn$1 = 0n;
|
|
7308
|
+
if (direction === "exact-out") {
|
|
7309
|
+
const swapOnlyDispatch = buildCreditWrappedDispatch({
|
|
7310
|
+
...creditWrapArgs,
|
|
7311
|
+
dispatch: {
|
|
7312
|
+
positionIdList: [],
|
|
7313
|
+
finalPositionIdList: [...params.existingPositionIds],
|
|
7314
|
+
positionSizes: [],
|
|
7315
|
+
tickAndSpreadLimits: [],
|
|
7316
|
+
usePremiaAsCollateral: false,
|
|
7317
|
+
builderCode: 0n
|
|
7318
|
+
}
|
|
7319
|
+
});
|
|
7320
|
+
const swapSimulation = await simulateDispatch({
|
|
7321
|
+
...simulateArgs,
|
|
7322
|
+
...swapOnlyDispatch
|
|
7323
|
+
});
|
|
7324
|
+
if (!swapSimulation.success || swapSimulation.tokenFlow === void 0) return {
|
|
7325
|
+
available: false,
|
|
7326
|
+
reason: "swap-unavailable",
|
|
7327
|
+
detail: swapSimulation.success ? "swap-only simulation returned no token flow" : `swap-only simulation reverted: ${swapSimulation.error.message}`,
|
|
7328
|
+
error: swapSimulation.success ? void 0 : swapSimulation.error
|
|
7329
|
+
};
|
|
7330
|
+
estimatedCounterAmount = abs(deltaAt(swapSimulation.tokenFlow, targetTokenIndex));
|
|
7331
|
+
maximumAmountIn$1 = padForSlippage(estimatedCounterAmount, params.slippageBps);
|
|
7332
|
+
const sourceBalance = balanceBeforeAt(swapSimulation.tokenFlow, targetTokenIndex);
|
|
7333
|
+
if (sourceBalance < maximumAmountIn$1) return {
|
|
7334
|
+
available: false,
|
|
7335
|
+
reason: "swap-unavailable",
|
|
7336
|
+
detail: `source balance ${sourceBalance} < maximumAmountIn ${maximumAmountIn$1} (estimated ${estimatedCounterAmount}, slippageBps ${params.slippageBps})`,
|
|
7337
|
+
error: new PanopticError("Insufficient collateral to fund the one-token-out swap")
|
|
7338
|
+
};
|
|
7339
|
+
}
|
|
7340
|
+
const wrappedDispatch = buildCreditWrappedDispatch({
|
|
7341
|
+
...creditWrapArgs,
|
|
7342
|
+
dispatch: params.dispatch
|
|
7343
|
+
});
|
|
7344
|
+
const wrappedSimulation = await simulateDispatch({
|
|
7345
|
+
...simulateArgs,
|
|
7346
|
+
...wrappedDispatch
|
|
7347
|
+
});
|
|
7348
|
+
if (!wrappedSimulation.success || wrappedSimulation.tokenFlow === void 0) return {
|
|
7349
|
+
available: false,
|
|
7350
|
+
reason: "wrap-unavailable",
|
|
7351
|
+
detail: wrappedSimulation.success ? "wrapped dispatch simulation returned no token flow" : `wrapped dispatch reverted: ${wrappedSimulation.error.message}`,
|
|
7352
|
+
error: wrappedSimulation.success ? void 0 : wrappedSimulation.error
|
|
7353
|
+
};
|
|
7354
|
+
if (direction === "exact-in" && baseTargetDelta !== null) estimatedCounterAmount = abs(deltaAt(wrappedSimulation.tokenFlow, targetTokenIndex) - baseTargetDelta);
|
|
7355
|
+
return {
|
|
7356
|
+
available: true,
|
|
7357
|
+
quote: {
|
|
7358
|
+
targetToken,
|
|
7359
|
+
otherToken,
|
|
7360
|
+
targetTokenIndex,
|
|
7361
|
+
otherTokenIndex,
|
|
7362
|
+
direction,
|
|
7363
|
+
swapAmount,
|
|
7364
|
+
estimatedCounterAmount,
|
|
7365
|
+
maximumAmountIn: maximumAmountIn$1,
|
|
7366
|
+
slippageBps: params.slippageBps,
|
|
7367
|
+
netTargetChange: deltaAt(wrappedSimulation.tokenFlow, targetTokenIndex),
|
|
7368
|
+
residualOtherChange: deltaAt(wrappedSimulation.tokenFlow, otherTokenIndex),
|
|
7369
|
+
creditTokenId: credit.tokenId,
|
|
7370
|
+
dispatch: wrappedDispatch,
|
|
7371
|
+
tokenFlow: wrappedSimulation.tokenFlow,
|
|
7372
|
+
_meta: wrappedSimulation._meta
|
|
7373
|
+
}
|
|
7374
|
+
};
|
|
7375
|
+
}
|
|
7376
|
+
|
|
6601
7377
|
//#endregion
|
|
6602
7378
|
//#region src/panoptic/v2/abis/poolManager.ts
|
|
6603
7379
|
/**
|
|
@@ -7732,5 +8508,5 @@ function createEventPoller(params) {
|
|
|
7732
8508
|
}
|
|
7733
8509
|
|
|
7734
8510
|
//#endregion
|
|
7735
|
-
export { DEFAULT_RECONNECT_CONFIG, REQUIRED_BASE_ERROR_SENTINEL, addPendingPosition, addTrackedChunks, buildTokenShortfallRecoveryDispatch, calculateAccountGreeksPure, calculateSpreadWad, checkCollateralAcrossTicks, cleanupStalePendingPositions, clearPendingPositions, clearTrackedChunks, clearTradeHistory, computeV4PoolId, confirmPendingPosition, convertToAssets, convertToShares, createEventPoller, createEventSubscription, createFlowNeutralTokenId, createPoolFormatters, decodePanopticTokenURI, encodePoolKeyBytes, encodeV3PoolKeyBytes, estimateBlockNumbers, estimateCollateralRequired, failPendingPosition, formatBlockNumber, formatBps, formatCompact, formatDatetime, formatDuration, formatDurationSeconds, formatFeeTier, formatGas, formatGwei, formatPoolIdHex, formatRatioPercent, formatTimestamp, formatTimestampLocale, formatTokenIdHex, formatTokenIdShort, formatTxHash, formatUtilization, formatWei, getAccountBuyingPower, getAccountGreeks, getAccountHistory, getAccountPremia, getChunkLiquidities, getChunkSpreads, getClosedPositions, getCollateralSharePrices, getCollateralTotalAssetsBatch, getDeltaHedgeParams, getEnforcedTickLimits, getFactoryConstructMetadata, getFactoryOwnerOf, getFactoryTokenURI, getGuardianUnlockState, getItmAmounts, getMarginBuffer, getMaxPositionSize, getMaxRedeem, getMaxWithdrawable, getNativeTokenPrice, getNotEnoughTokensError, getOpenPositionPreview, getPanopticPoolAddress, getPanopticPoolFromPoolId, getPendingPositions, getPoolDeploymentBlock, getPoolDisplayId, getPoolLiquidities, getPortfolioValue, getPositionChunkData, getPositionEnrichmentData, getPositionsWithPremia, getPriceHistory, getRealizedPnL, getRequiredCreditForITM, getSafeMode, getStreamiaHistory, getSyncStatus, getTokenListId, getTrackedChunks, getTradeHistory, getUniswapFeeHistory, getUniswapV3PoolFromId, getUniswapV3PoolInfo, getUniswapV3PoolLiquidities, getUniswapV4PoolBasicState, getUniswapV4PoolInfo, getUniswapV4PoolKeyFromId, getUniswapV4PoolLiquidities, interpolateBlocks, minePoolAddress, minePoolAddressLocalAsync, multicallRead, optimizeTokenIdRiskPartners, parseBps, parseCollateralLog, parsePoolLog, parseTokenListId, previewDeposit, previewMint, previewRedeem, previewWithdraw, quoteTokenShortfallRecovery, reconstructFromEvents, removeTrackedChunks, resolveBlockNumbers, resolvePanopticPoolFromPoolId, resolveUniswapV4PoolKey, saveClosedPosition, scanChunks, simulateBatchDispatch, simulateClosePosition, simulateDeployNewPool, simulateDeposit, simulateDispatch, simulateForceExercise, simulateLiquidate, simulateSFPMBurn, simulateSFPMMint, simulateSettle, simulateSwapExactIn, simulateSwapExactOut, simulateWithdraw, truncateAddress, watchEvents };
|
|
7736
|
-
//# sourceMappingURL=v2-
|
|
8511
|
+
export { DEFAULT_MIN_SWAP_RATIO_BPS, DEFAULT_RECONNECT_CONFIG, REQUIRED_BASE_ERROR_SENTINEL, addPendingPosition, addTrackedChunks, buildCreditWrappedDispatch, buildSfpmSwapCalldata, buildSfpmSwapPlan, buildTokenShortfallRecoveryDispatch, calculateAccountGreeksPure, calculateSpreadWad, checkCollateralAcrossTicks, cleanupStalePendingPositions, clearPendingPositions, clearTrackedChunks, clearTradeHistory, computeV4PoolId, confirmPendingPosition, convertToAssets, convertToShares, createEventPoller, createEventSubscription, createFlowNeutralTokenId, createPoolFormatters, decodePanopticTokenURI, encodePoolKeyBytes, encodeV3PoolKeyBytes, ensureSfpmV3PoolInitialized, estimateBlockNumbers, 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, getPoolDeploymentBlock, 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, minePoolAddress, minePoolAddressLocalAsync, multicallRead, optimizeTokenIdRiskPartners, parseBps, parseCollateralLog, parsePoolLog, parseTokenListId, previewDeposit, previewMint, previewRedeem, previewWithdraw, quoteOneTokenFlow, quoteSfpmSwap, quoteTokenShortfallRecovery, reconstructFromEvents, removeTrackedChunks, resolveBlockNumbers, resolvePanopticPoolFromPoolId, resolveUniswapV4PoolKey, saveClosedPosition, scanChunks, simulateBatchDispatch, simulateClosePosition, simulateDeployNewPool, simulateDeposit, simulateDispatch, simulateForceExercise, simulateLiquidate, simulateSFPMBurn, simulateSFPMMint, simulateSettle, simulateSwapExactIn, simulateSwapExactOut, simulateWithdraw, slippageBpsToTickDistance, truncateAddress, watchEvents };
|
|
8512
|
+
//# sourceMappingURL=v2-D0dEatKb.js.map
|