@panoptic-eng/sdk 1.0.63 → 1.0.65

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.
Files changed (36) hide show
  1. package/README.md +1 -1
  2. package/dist/StateView-q4yMpBY6.js +323 -0
  3. package/dist/cow/index.d.ts +1 -1
  4. package/dist/cow/index.js +1 -1
  5. package/dist/cow/index.js.map +1 -1
  6. package/dist/{cow-BsSaoahK.js → cow-BU9YOHkh.js} +1 -1
  7. package/dist/index.d.ts +34 -34
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +7 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/{irm-BDlcUNgJ.js → irm-DGyKOQXz.js} +4 -326
  12. package/dist/panoptic/v2/index.d.ts +161 -137
  13. package/dist/panoptic/v2/index.d.ts.map +1 -1
  14. package/dist/panoptic/v2/index.js +61 -51
  15. package/dist/panoptic/v2/index.js.map +1 -1
  16. package/dist/panoptic/v2/react-public.d.ts +168 -144
  17. package/dist/panoptic/v2/react-public.d.ts.map +1 -1
  18. package/dist/panoptic/v2/react-public.js +64 -54
  19. package/dist/panoptic/v2/react-public.js.map +1 -1
  20. package/dist/{rates-BwZnK0tG.js → rates-Y0Pbv1_x.js} +4 -4
  21. package/dist/{router-pm9PDlyH.js → router-CheXbrfz.js} +2 -2
  22. package/dist/{router-Dejb6MWu.js → router-DxE-iwYF.js} +304 -6
  23. package/dist/{transactionFees-aXQlx-lq.js → transactionFees-BF033Mob.js} +1 -1
  24. package/dist/uniswap/index.d.ts +194 -4
  25. package/dist/uniswap/index.d.ts.map +1 -1
  26. package/dist/uniswap/index.js +1316 -789
  27. package/dist/uniswap/index.js.map +1 -1
  28. package/dist/{v2-ccGPXWvq.js → v2-QFSAShVj.js} +29 -316
  29. package/dist/{writes--fM_8ggw.js → writes-BA21eyGF.js} +38 -38
  30. package/dist/zodiac/index.d.ts +3 -3
  31. package/dist/zodiac/index.js +3 -3
  32. package/dist/zodiac/index.js.map +1 -1
  33. package/package.json +1 -1
  34. /package/dist/{chainDeployments-BhXMBZ4B.js → chainDeployments-Do4NaZA_.js} +0 -0
  35. /package/dist/{greeks-CNi1-cnp.js → greeks-CGtgLUyh.js} +0 -0
  36. /package/dist/{providers-1WdiaRbY.js → providers-DubVMHWU.js} +0 -0
@@ -1,5 +1,7 @@
1
1
  import Decimal from "decimal.js";
2
- import { BaseError, ContractFunctionRevertedError, decodeAbiParameters, decodeErrorResult, decodeEventLog, encodeAbiParameters, encodeFunctionData, encodePacked, erc20Abi, getAbiItem, isAddressEqual, keccak256, maxUint256, parseAbi, toFunctionSelector, zeroAddress } from "viem";
2
+ import { BaseError, ContractFunctionRevertedError, ExecutionRevertedError, decodeAbiParameters, decodeErrorResult, decodeEventLog, encodeAbiParameters, encodeFunctionData, encodePacked, erc20Abi, getAbiItem, isAddressEqual, keccak256, maxUint256, parseAbi, toFunctionSelector, zeroAddress } from "viem";
3
+ import { GraphQLClient } from "graphql-request";
4
+ import { z } from "zod";
3
5
 
4
6
  //#region src/uniswap/estimateLpFees.ts
5
7
  const D$1 = Decimal.clone({ precision: 60 });
@@ -126,6 +128,28 @@ function estimateLpFees({ candles, ranges, feePips }) {
126
128
  };
127
129
  }
128
130
 
131
+ //#endregion
132
+ //#region src/panoptic/v2/clients/blockMeta.ts
133
+ /**
134
+ * Get block metadata for a given block.
135
+ * Used to tag all read results with same-block consistency proof.
136
+ *
137
+ * @param params - The parameters
138
+ * @returns Block metadata
139
+ */
140
+ async function getBlockMeta(params) {
141
+ const { client, blockNumber } = params;
142
+ const block = await client.getBlock({
143
+ blockNumber,
144
+ includeTransactions: false
145
+ });
146
+ return {
147
+ blockNumber: block.number,
148
+ blockHash: block.hash,
149
+ blockTimestamp: block.timestamp
150
+ };
151
+ }
152
+
129
153
  //#endregion
130
154
  //#region src/panoptic/v2/utils/constants.ts
131
155
  /**
@@ -158,7 +182,7 @@ const NO_UPPER_LIQUIDATION_TICK = (1n << 23n) - 1n;
158
182
 
159
183
  //#endregion
160
184
  //#region src/panoptic/v2/formatters/tick.ts
161
- const Q192$5 = 1n << 192n;
185
+ const Q192$6 = 1n << 192n;
162
186
  const RAW_PRICE_PRECISION = 40n;
163
187
  function pow10(exponent) {
164
188
  if (exponent < 0n) throw new RangeError("Exponent must be non-negative");
@@ -216,7 +240,7 @@ const MAX_SQRT_PRICE_X96 = tickToSqrtPriceX96(MAX_TICK);
216
240
  function getPriceRatioFromSqrtPriceX96(sqrtPriceX96) {
217
241
  return {
218
242
  numerator: sqrtPriceX96 * sqrtPriceX96,
219
- denominator: Q192$5
243
+ denominator: Q192$6
220
244
  };
221
245
  }
222
246
  function getRawPriceRatio(tick) {
@@ -247,137 +271,872 @@ function tickToPrice(tick) {
247
271
  }
248
272
 
249
273
  //#endregion
250
- //#region src/panoptic/v2/errors/base.ts
251
- /**
252
- * Base error class for the Panoptic v2 SDK.
253
- * @module v2/errors/base
254
- */
274
+ //#region src/panoptic/v2/abis/stateView.ts
255
275
  /**
256
- * Base error class for all Panoptic SDK errors.
257
- * All errors thrown by the SDK extend this class.
258
- *
259
- * @example
260
- * ```typescript
261
- * try {
262
- * await openPosition(config, params)
263
- * } catch (error) {
264
- * if (error instanceof PanopticError) {
265
- * console.log('Panoptic error:', error.name, error.message)
266
- * console.log('Original cause:', error.cause)
267
- * }
268
- * }
269
- * ```
276
+ * Minimal Uniswap V4 StateView ABI for fee growth reads.
277
+ * Only includes functions needed by streamia history.
270
278
  */
271
- var PanopticError = class extends Error {
272
- name = "PanopticError";
273
- /** The Solidity error name (e.g. 'PriceBoundFail', 'InputListFail'). Set by the parser. */
274
- errorName;
275
- /**
276
- * Creates a new PanopticError.
277
- *
278
- * @param message - Human-readable error message
279
- * @param cause - Optional underlying error that caused this error
280
- */
281
- constructor(message, cause) {
282
- super(message);
283
- this.cause = cause;
284
- if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
285
- Object.setPrototypeOf(this, new.target.prototype);
279
+ const stateViewAbi = [
280
+ {
281
+ inputs: [{
282
+ internalType: "PoolId",
283
+ name: "poolId",
284
+ type: "bytes32"
285
+ }],
286
+ name: "getSlot0",
287
+ outputs: [
288
+ {
289
+ internalType: "uint160",
290
+ name: "sqrtPriceX96",
291
+ type: "uint160"
292
+ },
293
+ {
294
+ internalType: "int24",
295
+ name: "tick",
296
+ type: "int24"
297
+ },
298
+ {
299
+ internalType: "uint24",
300
+ name: "protocolFee",
301
+ type: "uint24"
302
+ },
303
+ {
304
+ internalType: "uint24",
305
+ name: "lpFee",
306
+ type: "uint24"
307
+ }
308
+ ],
309
+ stateMutability: "view",
310
+ type: "function"
311
+ },
312
+ {
313
+ inputs: [{
314
+ internalType: "PoolId",
315
+ name: "poolId",
316
+ type: "bytes32"
317
+ }],
318
+ name: "getFeeGrowthGlobals",
319
+ outputs: [{
320
+ internalType: "uint256",
321
+ name: "feeGrowthGlobal0",
322
+ type: "uint256"
323
+ }, {
324
+ internalType: "uint256",
325
+ name: "feeGrowthGlobal1",
326
+ type: "uint256"
327
+ }],
328
+ stateMutability: "view",
329
+ type: "function"
330
+ },
331
+ {
332
+ inputs: [{
333
+ internalType: "PoolId",
334
+ name: "poolId",
335
+ type: "bytes32"
336
+ }, {
337
+ internalType: "int24",
338
+ name: "tick",
339
+ type: "int24"
340
+ }],
341
+ name: "getTickInfo",
342
+ outputs: [
343
+ {
344
+ internalType: "uint128",
345
+ name: "liquidityGross",
346
+ type: "uint128"
347
+ },
348
+ {
349
+ internalType: "int128",
350
+ name: "liquidityNet",
351
+ type: "int128"
352
+ },
353
+ {
354
+ internalType: "uint256",
355
+ name: "feeGrowthOutside0X128",
356
+ type: "uint256"
357
+ },
358
+ {
359
+ internalType: "uint256",
360
+ name: "feeGrowthOutside1X128",
361
+ type: "uint256"
362
+ }
363
+ ],
364
+ stateMutability: "view",
365
+ type: "function"
366
+ },
367
+ {
368
+ inputs: [{
369
+ internalType: "PoolId",
370
+ name: "poolId",
371
+ type: "bytes32"
372
+ }],
373
+ name: "getLiquidity",
374
+ outputs: [{
375
+ internalType: "uint128",
376
+ name: "liquidity",
377
+ type: "uint128"
378
+ }],
379
+ stateMutability: "view",
380
+ type: "function"
286
381
  }
287
- };
382
+ ];
288
383
 
289
384
  //#endregion
290
- //#region src/panoptic/v2/errors/contract.ts
291
- /**
292
- * The account is not solvent enough to perform the desired action.
293
- * @see Errors.sol:9
294
- */
295
- var AccountInsolventError = class extends PanopticError {
296
- name = "AccountInsolventError";
297
- constructor(solvent, numberOfTicks, cause) {
298
- super(`Account insolvent: solvent=${solvent}, numberOfTicks=${numberOfTicks}`, cause);
299
- this.solvent = solvent;
300
- this.numberOfTicks = numberOfTicks;
301
- }
302
- };
303
- /**
304
- * Position is still solvent and cannot be liquidated.
305
- * @see Errors.sol:84
306
- */
307
- var NotMarginCalledError = class extends PanopticError {
308
- name = "NotMarginCalledError";
309
- constructor(cause) {
310
- super("Position is still solvent and cannot be liquidated", cause);
311
- }
312
- };
313
- /**
314
- * The user does not own enough assets to open/close a position.
315
- * @see Errors.sol:78
316
- */
317
- var NotEnoughTokensError = class extends PanopticError {
318
- name = "NotEnoughTokensError";
319
- constructor(tokenAddress, assetsRequested, assetBalance, cause) {
320
- super(`Not enough tokens: requested=${assetsRequested}, balance=${assetBalance}, token=${tokenAddress}`, cause);
321
- this.tokenAddress = tokenAddress;
322
- this.assetsRequested = assetsRequested;
323
- this.assetBalance = assetBalance;
324
- }
325
- };
326
- /**
327
- * There is not enough available liquidity in the chunk for a long leg.
328
- * @see Errors.sol:75
329
- */
330
- var NotEnoughLiquidityInChunkError = class extends PanopticError {
331
- name = "NotEnoughLiquidityInChunkError";
332
- constructor(cause) {
333
- super("Not enough liquidity in chunk for long leg creation or short leg closure", cause);
334
- }
335
- };
336
- /**
337
- * There is not enough available liquidity to fulfill a credit.
338
- * @see Errors.sol:47
339
- */
340
- var InsufficientCreditLiquidityError = class extends PanopticError {
341
- name = "InsufficientCreditLiquidityError";
342
- constructor(cause) {
343
- super("Insufficient credit liquidity available in the PanopticPool", cause);
344
- }
345
- };
346
- /**
347
- * The amount deposited is larger than the maximum permitted.
348
- * @see Errors.sol:25
349
- */
350
- var DepositTooLargeError = class extends PanopticError {
351
- name = "DepositTooLargeError";
352
- constructor(cause) {
353
- super("Deposit amount exceeds maximum permitted", cause);
354
- }
355
- };
356
- /**
357
- * Attempted to withdraw/redeem less than a single asset.
358
- * @see Errors.sol:16
359
- */
360
- var BelowMinimumRedemptionError = class extends PanopticError {
361
- name = "BelowMinimumRedemptionError";
362
- constructor(cause) {
363
- super("Redemption amount below minimum threshold", cause);
364
- }
365
- };
366
- /**
367
- * Attempted to withdraw/redeem more than available.
368
- * @see Errors.sol:35
369
- */
370
- var ExceedsMaximumRedemptionError = class extends PanopticError {
371
- name = "ExceedsMaximumRedemptionError";
372
- constructor(cause) {
373
- super("Redemption exceeds maximum available (liquidity, shares, or open positions)", cause);
374
- }
375
- };
385
+ //#region src/panoptic/v2/abis/uniswapV3Pool.ts
376
386
  /**
377
- * Mints/burns of a position returns no collateral requirement.
378
- * @see Errors.sol:141
387
+ * Minimal Uniswap V3 Pool ABI for fee growth reads.
388
+ * Only includes functions needed by streamia history.
379
389
  */
380
- var ZeroCollateralRequirementError = class extends PanopticError {
390
+ const uniswapV3PoolAbi = [
391
+ {
392
+ inputs: [],
393
+ name: "slot0",
394
+ outputs: [
395
+ {
396
+ internalType: "uint160",
397
+ name: "sqrtPriceX96",
398
+ type: "uint160"
399
+ },
400
+ {
401
+ internalType: "int24",
402
+ name: "tick",
403
+ type: "int24"
404
+ },
405
+ {
406
+ internalType: "uint16",
407
+ name: "observationIndex",
408
+ type: "uint16"
409
+ },
410
+ {
411
+ internalType: "uint16",
412
+ name: "observationCardinality",
413
+ type: "uint16"
414
+ },
415
+ {
416
+ internalType: "uint16",
417
+ name: "observationCardinalityNext",
418
+ type: "uint16"
419
+ },
420
+ {
421
+ internalType: "uint8",
422
+ name: "feeProtocol",
423
+ type: "uint8"
424
+ },
425
+ {
426
+ internalType: "bool",
427
+ name: "unlocked",
428
+ type: "bool"
429
+ }
430
+ ],
431
+ stateMutability: "view",
432
+ type: "function"
433
+ },
434
+ {
435
+ inputs: [],
436
+ name: "feeGrowthGlobal0X128",
437
+ outputs: [{
438
+ internalType: "uint256",
439
+ name: "",
440
+ type: "uint256"
441
+ }],
442
+ stateMutability: "view",
443
+ type: "function"
444
+ },
445
+ {
446
+ inputs: [],
447
+ name: "feeGrowthGlobal1X128",
448
+ outputs: [{
449
+ internalType: "uint256",
450
+ name: "",
451
+ type: "uint256"
452
+ }],
453
+ stateMutability: "view",
454
+ type: "function"
455
+ },
456
+ {
457
+ inputs: [{
458
+ internalType: "int24",
459
+ name: "",
460
+ type: "int24"
461
+ }],
462
+ name: "ticks",
463
+ outputs: [
464
+ {
465
+ internalType: "uint128",
466
+ name: "liquidityGross",
467
+ type: "uint128"
468
+ },
469
+ {
470
+ internalType: "int128",
471
+ name: "liquidityNet",
472
+ type: "int128"
473
+ },
474
+ {
475
+ internalType: "uint256",
476
+ name: "feeGrowthOutside0X128",
477
+ type: "uint256"
478
+ },
479
+ {
480
+ internalType: "uint256",
481
+ name: "feeGrowthOutside1X128",
482
+ type: "uint256"
483
+ },
484
+ {
485
+ internalType: "int56",
486
+ name: "tickCumulativeOutside",
487
+ type: "int56"
488
+ },
489
+ {
490
+ internalType: "uint160",
491
+ name: "secondsPerLiquidityOutsideX128",
492
+ type: "uint160"
493
+ },
494
+ {
495
+ internalType: "uint32",
496
+ name: "secondsOutside",
497
+ type: "uint32"
498
+ },
499
+ {
500
+ internalType: "bool",
501
+ name: "initialized",
502
+ type: "bool"
503
+ }
504
+ ],
505
+ stateMutability: "view",
506
+ type: "function"
507
+ },
508
+ {
509
+ inputs: [],
510
+ name: "liquidity",
511
+ outputs: [{
512
+ internalType: "uint128",
513
+ name: "",
514
+ type: "uint128"
515
+ }],
516
+ stateMutability: "view",
517
+ type: "function"
518
+ },
519
+ {
520
+ inputs: [],
521
+ name: "fee",
522
+ outputs: [{
523
+ internalType: "uint24",
524
+ name: "",
525
+ type: "uint24"
526
+ }],
527
+ stateMutability: "view",
528
+ type: "function"
529
+ },
530
+ {
531
+ inputs: [],
532
+ name: "token0",
533
+ outputs: [{
534
+ internalType: "address",
535
+ name: "",
536
+ type: "address"
537
+ }],
538
+ stateMutability: "view",
539
+ type: "function"
540
+ },
541
+ {
542
+ inputs: [],
543
+ name: "token1",
544
+ outputs: [{
545
+ internalType: "address",
546
+ name: "",
547
+ type: "address"
548
+ }],
549
+ stateMutability: "view",
550
+ type: "function"
551
+ },
552
+ {
553
+ inputs: [],
554
+ name: "tickSpacing",
555
+ outputs: [{
556
+ internalType: "int24",
557
+ name: "",
558
+ type: "int24"
559
+ }],
560
+ stateMutability: "view",
561
+ type: "function"
562
+ }
563
+ ];
564
+
565
+ //#endregion
566
+ //#region src/panoptic/v2/reads/priceHistory.ts
567
+ /**
568
+ * Get historical price data (tick + sqrtPriceX96) for a pool across multiple blocks.
569
+ *
570
+ * @param params - The parameters
571
+ * @returns Price snapshots at each block
572
+ *
573
+ * @example
574
+ * ```typescript
575
+ * const { snapshots } = await getPriceHistory({
576
+ * client,
577
+ * blockNumbers: [18000000n, 18000100n, 18000200n],
578
+ * poolConfig: { version: 'v3', poolAddress: '0x...' },
579
+ * })
580
+ *
581
+ * for (const snap of snapshots) {
582
+ * console.log(`Block ${snap.blockNumber}: tick=${snap.tick}`)
583
+ * }
584
+ * ```
585
+ */
586
+ async function getPriceHistory(params) {
587
+ const { client, blockNumbers, poolConfig } = params;
588
+ if (blockNumbers.length === 0) {
589
+ const _meta$1 = params._meta ?? await getBlockMeta({ client });
590
+ return {
591
+ snapshots: [],
592
+ _meta: _meta$1
593
+ };
594
+ }
595
+ const slot0Requests = blockNumbers.map((bn) => fetchSlot0(client, bn, poolConfig));
596
+ const [slot0Results, _meta] = await Promise.all([Promise.all(slot0Requests), params._meta ? Promise.resolve(params._meta) : getBlockMeta({ client })]);
597
+ const snapshots = slot0Results.map((result, i) => ({
598
+ blockNumber: blockNumbers[i],
599
+ tick: result.tick,
600
+ sqrtPriceX96: result.sqrtPriceX96
601
+ }));
602
+ return {
603
+ snapshots,
604
+ _meta
605
+ };
606
+ }
607
+ async function fetchSlot0(client, blockNumber, poolConfig) {
608
+ if (poolConfig.version === "v3") {
609
+ const result = await client.readContract({
610
+ address: poolConfig.poolAddress,
611
+ abi: uniswapV3PoolAbi,
612
+ functionName: "slot0",
613
+ blockNumber
614
+ });
615
+ return {
616
+ sqrtPriceX96: result[0],
617
+ tick: result[1]
618
+ };
619
+ } else {
620
+ const result = await client.readContract({
621
+ address: poolConfig.stateViewAddress,
622
+ abi: stateViewAbi,
623
+ functionName: "getSlot0",
624
+ args: [poolConfig.poolId],
625
+ blockNumber
626
+ });
627
+ return {
628
+ sqrtPriceX96: result[0],
629
+ tick: result[1]
630
+ };
631
+ }
632
+ }
633
+
634
+ //#endregion
635
+ //#region src/panoptic/v2/reads/uniswapLpPosition.ts
636
+ const nfpmAbi = [{
637
+ type: "function",
638
+ name: "positions",
639
+ inputs: [{
640
+ name: "tokenId",
641
+ type: "uint256"
642
+ }],
643
+ outputs: [
644
+ {
645
+ name: "nonce",
646
+ type: "uint96"
647
+ },
648
+ {
649
+ name: "operator",
650
+ type: "address"
651
+ },
652
+ {
653
+ name: "token0",
654
+ type: "address"
655
+ },
656
+ {
657
+ name: "token1",
658
+ type: "address"
659
+ },
660
+ {
661
+ name: "fee",
662
+ type: "uint24"
663
+ },
664
+ {
665
+ name: "tickLower",
666
+ type: "int24"
667
+ },
668
+ {
669
+ name: "tickUpper",
670
+ type: "int24"
671
+ },
672
+ {
673
+ name: "liquidity",
674
+ type: "uint128"
675
+ },
676
+ {
677
+ name: "feeGrowthInside0LastX128",
678
+ type: "uint256"
679
+ },
680
+ {
681
+ name: "feeGrowthInside1LastX128",
682
+ type: "uint256"
683
+ },
684
+ {
685
+ name: "tokensOwed0",
686
+ type: "uint128"
687
+ },
688
+ {
689
+ name: "tokensOwed1",
690
+ type: "uint128"
691
+ }
692
+ ],
693
+ stateMutability: "view"
694
+ }, {
695
+ type: "function",
696
+ name: "collect",
697
+ inputs: [{
698
+ name: "params",
699
+ type: "tuple",
700
+ components: [
701
+ {
702
+ name: "tokenId",
703
+ type: "uint256"
704
+ },
705
+ {
706
+ name: "recipient",
707
+ type: "address"
708
+ },
709
+ {
710
+ name: "amount0Max",
711
+ type: "uint128"
712
+ },
713
+ {
714
+ name: "amount1Max",
715
+ type: "uint128"
716
+ }
717
+ ]
718
+ }],
719
+ outputs: [{
720
+ name: "amount0",
721
+ type: "uint256"
722
+ }, {
723
+ name: "amount1",
724
+ type: "uint256"
725
+ }],
726
+ stateMutability: "payable"
727
+ }];
728
+ const MAX_UINT128$3 = 2n ** 128n - 1n;
729
+ const MAX_UINT256$1 = 2n ** 256n - 1n;
730
+ const Q128 = 2n ** 128n;
731
+ /**
732
+ * Whether an error thrown by a viem contract call is an on-chain revert (as
733
+ * opposed to a transport/RPC failure such as a timeout or rate limit).
734
+ */
735
+ function isContractRevert(error) {
736
+ return error instanceof BaseError && error.walk((err) => err instanceof ContractFunctionRevertedError || err instanceof ExecutionRevertedError) != null;
737
+ }
738
+ /**
739
+ * Fetch a Uniswap V3 LP position's state and uncollected fees.
740
+ *
741
+ * Fees come from simulating `collect` with max amounts as the owner — one
742
+ * eth_call returning the exact claimable amounts (tokensOwed + fee growth
743
+ * since the last poke). The simulation is best-effort: if it reverts (e.g.
744
+ * an empty position), fees fall back to 0.
745
+ */
746
+ async function getUniswapV3LpPositionState(params) {
747
+ const { client, nfpmAddress, tokenId, owner, blockNumber } = params;
748
+ const _meta = await getBlockMeta({
749
+ client,
750
+ blockNumber
751
+ });
752
+ const position = await client.readContract({
753
+ address: nfpmAddress,
754
+ abi: nfpmAbi,
755
+ functionName: "positions",
756
+ args: [tokenId],
757
+ blockNumber: _meta.blockNumber
758
+ });
759
+ const [, , token0, token1, fee, tickLower, tickUpper, liquidity] = position;
760
+ let fees0 = 0n;
761
+ let fees1 = 0n;
762
+ try {
763
+ const { result } = await client.simulateContract({
764
+ address: nfpmAddress,
765
+ abi: nfpmAbi,
766
+ functionName: "collect",
767
+ args: [{
768
+ tokenId,
769
+ recipient: owner,
770
+ amount0Max: MAX_UINT128$3,
771
+ amount1Max: MAX_UINT128$3
772
+ }],
773
+ account: owner,
774
+ blockNumber: _meta.blockNumber
775
+ });
776
+ [fees0, fees1] = result;
777
+ } catch (error) {
778
+ if (!isContractRevert(error)) throw error;
779
+ }
780
+ return {
781
+ token0,
782
+ token1,
783
+ fee: Number(fee),
784
+ tickLower: Number(tickLower),
785
+ tickUpper: Number(tickUpper),
786
+ liquidity,
787
+ fees0,
788
+ fees1,
789
+ _meta
790
+ };
791
+ }
792
+
793
+ //#endregion
794
+ //#region src/uniswap/lpGreeks.ts
795
+ const Q96$4 = 1n << 96n;
796
+ const Q192$5 = 1n << 192n;
797
+ /**
798
+ * Compute the token0/token1 amounts backing `liquidity` over `[sqrtA, sqrtB]`
799
+ * at the current price `sqrtP`, mirroring Uniswap's `LiquidityAmounts`
800
+ * (`getAmountsForLiquidity`). All sqrt prices are X96. The current price is
801
+ * clamped into the range, so out-of-range positions collapse to a single token.
802
+ */
803
+ function getAmountsForLiquidity(sqrtPriceX96, sqrtRatioAX96, sqrtRatioBX96, liquidity) {
804
+ const [sqrtA, sqrtB] = sqrtRatioAX96 <= sqrtRatioBX96 ? [sqrtRatioAX96, sqrtRatioBX96] : [sqrtRatioBX96, sqrtRatioAX96];
805
+ const sqrtC = sqrtPriceX96 < sqrtA ? sqrtA : sqrtPriceX96 > sqrtB ? sqrtB : sqrtPriceX96;
806
+ const amount0 = sqrtC < sqrtB ? liquidity * (sqrtB - sqrtC) * Q96$4 / (sqrtC * sqrtB) : 0n;
807
+ const amount1 = sqrtC > sqrtA ? liquidity * (sqrtC - sqrtA) / Q96$4 : 0n;
808
+ return {
809
+ amount0,
810
+ amount1
811
+ };
812
+ }
813
+ /**
814
+ * Greeks (value, delta, gamma) for a Uniswap LP position in the chosen asset
815
+ * frame. See the module docs for the unit conventions.
816
+ *
817
+ * Closed forms (in-range, numeraire = token1 / asset = token0):
818
+ * value = amount1 + amount0·P (P = sqrtP² / 2^192)
819
+ * delta = amount0 (= dV/dP)
820
+ * gamma = P²·d²V/dP² = -L·sqrt(P)/2 (short gamma)
821
+ * The `assetIndex = 1` frame is the symmetric inverse (numeraire = token0).
822
+ * Gamma is zero when the price is outside the range (no curvature there).
823
+ */
824
+ function getLpGreeks(input) {
825
+ const { liquidity, tickLower, tickUpper, currentTick, assetIndex } = input;
826
+ const sqrtP = input.sqrtPriceX96 ?? tickToSqrtPriceX96(currentTick);
827
+ if (sqrtP <= 0n) throw new RangeError("Invalid sqrt price");
828
+ const sqrtA = tickToSqrtPriceX96(tickLower);
829
+ const sqrtB = tickToSqrtPriceX96(tickUpper);
830
+ const { amount0, amount1 } = getAmountsForLiquidity(sqrtP, sqrtA, sqrtB, liquidity);
831
+ const sqrtP2 = sqrtP * sqrtP;
832
+ const inRange = sqrtP > sqrtA && sqrtP < sqrtB;
833
+ if (assetIndex === 0) {
834
+ const value$1 = amount1 + amount0 * sqrtP2 / Q192$5;
835
+ const delta$1 = amount0;
836
+ const gamma$1 = inRange ? -(liquidity * sqrtP) / (2n * Q96$4) : 0n;
837
+ return {
838
+ value: value$1,
839
+ delta: delta$1,
840
+ gamma: gamma$1
841
+ };
842
+ }
843
+ const value = amount0 + amount1 * Q192$5 / sqrtP2;
844
+ const delta = amount1;
845
+ const gamma = inRange ? -(liquidity * Q96$4) / (2n * sqrtP) : 0n;
846
+ return {
847
+ value,
848
+ delta,
849
+ gamma
850
+ };
851
+ }
852
+
853
+ //#endregion
854
+ //#region src/uniswap/lpAccounting.ts
855
+ const Precision$2 = Decimal.clone({ precision: 80 });
856
+ const Q192$4 = (1n << 192n).toString();
857
+ function reconcileV3LpFees(events, claimable, endBlock) {
858
+ let collected0 = 0n;
859
+ let collected1 = 0n;
860
+ let removed0 = 0n;
861
+ let removed1 = 0n;
862
+ for (const event of events) {
863
+ if (event.amountSource !== "ExactEvent" || event.blockNumber > endBlock) throw new Error("Complete exact v3 history is required");
864
+ if (event.eventType === "Collect") {
865
+ collected0 += event.amount0;
866
+ collected1 += event.amount1;
867
+ } else if (event.eventType === "Burn") {
868
+ removed0 += event.amount0;
869
+ removed1 += event.amount1;
870
+ }
871
+ }
872
+ const fees0 = collected0 + claimable.amount0 - removed0;
873
+ const fees1 = collected1 + claimable.amount1 - removed1;
874
+ if (fees0 < 0n || fees1 < 0n) throw new Error("LP fee accounting does not reconcile");
875
+ return {
876
+ fees0,
877
+ fees1
878
+ };
879
+ }
880
+ /** V3 NFT cash-flow returns, including withdrawn principal still awaiting collection. */
881
+ function calculateV3LpAccounting({ events, inventory, claimable, prices, endBlock, token0Decimals, token1Decimals }) {
882
+ for (const decimals of [token0Decimals, token1Decimals]) if (!Number.isInteger(decimals) || decimals < 0 || decimals > 255) throw new RangeError("Invalid token decimals");
883
+ const priceByBlock = new Map(prices.map((point) => {
884
+ if (point.sqrtPriceX96 <= 0n) throw new RangeError("Invalid historical price");
885
+ return [point.blockNumber, new Precision$2(point.sqrtPriceX96.toString()).pow(2).div(Q192$4)];
886
+ }));
887
+ const priceAt = (block) => {
888
+ const price = priceByBlock.get(block);
889
+ if (!price) throw new Error("Historical price unavailable");
890
+ return price;
891
+ };
892
+ const { fees0, fees1 } = reconcileV3LpFees(events, claimable, endBlock);
893
+ const frame = (quoteIsToken0, decimals) => {
894
+ const scale = new Precision$2(10).pow(decimals);
895
+ const value = (amount0, amount1, block) => {
896
+ const price = priceAt(block);
897
+ return (quoteIsToken0 ? new Precision$2(amount0.toString()).plus(new Precision$2(amount1.toString()).div(price)) : new Precision$2(amount1.toString()).plus(new Precision$2(amount0.toString()).mul(price))).div(scale);
898
+ };
899
+ let deposited = new Precision$2(0);
900
+ let collected = new Precision$2(0);
901
+ for (const event of events) {
902
+ if (event.eventType === "Mint") deposited = deposited.plus(value(event.amount0, event.amount1, event.blockNumber));
903
+ if (event.eventType === "Collect") collected = collected.plus(value(event.amount0, event.amount1, event.blockNumber));
904
+ }
905
+ const endingValue = value(inventory.amount0 + claimable.amount0, inventory.amount1 + claimable.amount1, endBlock);
906
+ const pnl = endingValue.plus(collected).minus(deposited);
907
+ return {
908
+ pnl: pnl.toString(),
909
+ deposited: deposited.toString(),
910
+ pnlPercent: deposited.gt(0) ? pnl.div(deposited).mul(100).toString() : null
911
+ };
912
+ };
913
+ return {
914
+ fees0,
915
+ fees1,
916
+ claimable,
917
+ quote0: frame(true, token0Decimals),
918
+ quote1: frame(false, token1Decimals)
919
+ };
920
+ }
921
+ /** Reconcile v3 activity and historical prices at the subgraph's indexed block. */
922
+ async function getV3LpHistoryAccounting({ client, history, nfpmAddress, poolAddress, tickLower, tickUpper, token0Decimals, token1Decimals }) {
923
+ if (history.version !== 3) throw new Error("V4 fee collections are unavailable");
924
+ const tokenId = BigInt(history.positionId.slice(3));
925
+ const _meta = await getBlockMeta({
926
+ client,
927
+ blockNumber: history.blockNumber
928
+ });
929
+ if (_meta.blockHash.toLowerCase() !== history.blockHash.toLowerCase()) throw new Error("LP history checkpoint changed");
930
+ let liquidity = 0n;
931
+ for (const event of history.events) if (event.eventType !== "Collect") liquidity += event.eventType === "Mint" ? event.liquidity : -event.liquidity;
932
+ let claimable = {
933
+ amount0: 0n,
934
+ amount1: 0n
935
+ };
936
+ let owner;
937
+ try {
938
+ owner = await client.readContract({
939
+ address: nfpmAddress,
940
+ abi: parseAbi(["function ownerOf(uint256 tokenId) view returns (address)"]),
941
+ functionName: "ownerOf",
942
+ args: [tokenId],
943
+ blockNumber: history.blockNumber
944
+ });
945
+ } catch (error) {
946
+ const reverted = error instanceof BaseError && error.walk((cause) => cause instanceof ContractFunctionRevertedError || cause instanceof ExecutionRevertedError);
947
+ if (liquidity !== 0n || !(reverted instanceof ContractFunctionRevertedError || reverted instanceof ExecutionRevertedError)) throw error;
948
+ }
949
+ if (owner) {
950
+ const state = await getUniswapV3LpPositionState({
951
+ client,
952
+ nfpmAddress,
953
+ tokenId,
954
+ owner,
955
+ blockNumber: history.blockNumber
956
+ });
957
+ if (state.liquidity !== liquidity) throw new Error("LP liquidity history does not reconcile");
958
+ claimable = {
959
+ amount0: state.fees0,
960
+ amount1: state.fees1
961
+ };
962
+ }
963
+ const blocks = [...new Set([history.blockNumber, ...history.events.filter((event) => event.eventType !== "Burn").map((event) => event.blockNumber)])];
964
+ const feeTotals = reconcileV3LpFees(history.events, claimable, history.blockNumber);
965
+ const prices = [];
966
+ for (let index = 0; index < blocks.length; index += 16) {
967
+ const batch = blocks.slice(index, index + 16);
968
+ const result = await getPriceHistory({
969
+ client,
970
+ blockNumbers: batch,
971
+ poolConfig: {
972
+ version: "v3",
973
+ poolAddress
974
+ },
975
+ _meta
976
+ }).catch(() => null);
977
+ if (!result) return {
978
+ ...feeTotals,
979
+ claimable,
980
+ quote0: null,
981
+ quote1: null,
982
+ blockNumber: history.blockNumber,
983
+ timestamp: _meta.blockTimestamp
984
+ };
985
+ result.snapshots.forEach((point, offset) => prices.push({
986
+ blockNumber: batch[offset],
987
+ sqrtPriceX96: point.sqrtPriceX96
988
+ }));
989
+ }
990
+ const endingPrice = prices.find((price) => price.blockNumber === history.blockNumber);
991
+ if (!endingPrice) throw new Error("Ending price unavailable");
992
+ const inventory = getAmountsForLiquidity(endingPrice.sqrtPriceX96, tickToSqrtPriceX96(tickLower), tickToSqrtPriceX96(tickUpper), liquidity);
993
+ return {
994
+ ...calculateV3LpAccounting({
995
+ events: history.events,
996
+ inventory,
997
+ claimable,
998
+ prices,
999
+ endBlock: history.blockNumber,
1000
+ token0Decimals,
1001
+ token1Decimals
1002
+ }),
1003
+ blockNumber: history.blockNumber,
1004
+ timestamp: _meta.blockTimestamp
1005
+ };
1006
+ }
1007
+
1008
+ //#endregion
1009
+ //#region src/panoptic/v2/errors/base.ts
1010
+ /**
1011
+ * Base error class for the Panoptic v2 SDK.
1012
+ * @module v2/errors/base
1013
+ */
1014
+ /**
1015
+ * Base error class for all Panoptic SDK errors.
1016
+ * All errors thrown by the SDK extend this class.
1017
+ *
1018
+ * @example
1019
+ * ```typescript
1020
+ * try {
1021
+ * await openPosition(config, params)
1022
+ * } catch (error) {
1023
+ * if (error instanceof PanopticError) {
1024
+ * console.log('Panoptic error:', error.name, error.message)
1025
+ * console.log('Original cause:', error.cause)
1026
+ * }
1027
+ * }
1028
+ * ```
1029
+ */
1030
+ var PanopticError = class extends Error {
1031
+ name = "PanopticError";
1032
+ /** The Solidity error name (e.g. 'PriceBoundFail', 'InputListFail'). Set by the parser. */
1033
+ errorName;
1034
+ /**
1035
+ * Creates a new PanopticError.
1036
+ *
1037
+ * @param message - Human-readable error message
1038
+ * @param cause - Optional underlying error that caused this error
1039
+ */
1040
+ constructor(message, cause) {
1041
+ super(message);
1042
+ this.cause = cause;
1043
+ if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
1044
+ Object.setPrototypeOf(this, new.target.prototype);
1045
+ }
1046
+ };
1047
+
1048
+ //#endregion
1049
+ //#region src/panoptic/v2/errors/contract.ts
1050
+ /**
1051
+ * The account is not solvent enough to perform the desired action.
1052
+ * @see Errors.sol:9
1053
+ */
1054
+ var AccountInsolventError = class extends PanopticError {
1055
+ name = "AccountInsolventError";
1056
+ constructor(solvent, numberOfTicks, cause) {
1057
+ super(`Account insolvent: solvent=${solvent}, numberOfTicks=${numberOfTicks}`, cause);
1058
+ this.solvent = solvent;
1059
+ this.numberOfTicks = numberOfTicks;
1060
+ }
1061
+ };
1062
+ /**
1063
+ * Position is still solvent and cannot be liquidated.
1064
+ * @see Errors.sol:84
1065
+ */
1066
+ var NotMarginCalledError = class extends PanopticError {
1067
+ name = "NotMarginCalledError";
1068
+ constructor(cause) {
1069
+ super("Position is still solvent and cannot be liquidated", cause);
1070
+ }
1071
+ };
1072
+ /**
1073
+ * The user does not own enough assets to open/close a position.
1074
+ * @see Errors.sol:78
1075
+ */
1076
+ var NotEnoughTokensError = class extends PanopticError {
1077
+ name = "NotEnoughTokensError";
1078
+ constructor(tokenAddress, assetsRequested, assetBalance, cause) {
1079
+ super(`Not enough tokens: requested=${assetsRequested}, balance=${assetBalance}, token=${tokenAddress}`, cause);
1080
+ this.tokenAddress = tokenAddress;
1081
+ this.assetsRequested = assetsRequested;
1082
+ this.assetBalance = assetBalance;
1083
+ }
1084
+ };
1085
+ /**
1086
+ * There is not enough available liquidity in the chunk for a long leg.
1087
+ * @see Errors.sol:75
1088
+ */
1089
+ var NotEnoughLiquidityInChunkError = class extends PanopticError {
1090
+ name = "NotEnoughLiquidityInChunkError";
1091
+ constructor(cause) {
1092
+ super("Not enough liquidity in chunk for long leg creation or short leg closure", cause);
1093
+ }
1094
+ };
1095
+ /**
1096
+ * There is not enough available liquidity to fulfill a credit.
1097
+ * @see Errors.sol:47
1098
+ */
1099
+ var InsufficientCreditLiquidityError = class extends PanopticError {
1100
+ name = "InsufficientCreditLiquidityError";
1101
+ constructor(cause) {
1102
+ super("Insufficient credit liquidity available in the PanopticPool", cause);
1103
+ }
1104
+ };
1105
+ /**
1106
+ * The amount deposited is larger than the maximum permitted.
1107
+ * @see Errors.sol:25
1108
+ */
1109
+ var DepositTooLargeError = class extends PanopticError {
1110
+ name = "DepositTooLargeError";
1111
+ constructor(cause) {
1112
+ super("Deposit amount exceeds maximum permitted", cause);
1113
+ }
1114
+ };
1115
+ /**
1116
+ * Attempted to withdraw/redeem less than a single asset.
1117
+ * @see Errors.sol:16
1118
+ */
1119
+ var BelowMinimumRedemptionError = class extends PanopticError {
1120
+ name = "BelowMinimumRedemptionError";
1121
+ constructor(cause) {
1122
+ super("Redemption amount below minimum threshold", cause);
1123
+ }
1124
+ };
1125
+ /**
1126
+ * Attempted to withdraw/redeem more than available.
1127
+ * @see Errors.sol:35
1128
+ */
1129
+ var ExceedsMaximumRedemptionError = class extends PanopticError {
1130
+ name = "ExceedsMaximumRedemptionError";
1131
+ constructor(cause) {
1132
+ super("Redemption exceeds maximum available (liquidity, shares, or open positions)", cause);
1133
+ }
1134
+ };
1135
+ /**
1136
+ * Mints/burns of a position returns no collateral requirement.
1137
+ * @see Errors.sol:141
1138
+ */
1139
+ var ZeroCollateralRequirementError = class extends PanopticError {
381
1140
  name = "ZeroCollateralRequirementError";
382
1141
  constructor(cause) {
383
1142
  super("Position mint/burn returned zero collateral requirement", cause);
@@ -586,7 +1345,7 @@ var NoLegsExercisableError = class extends PanopticError {
586
1345
  var NotALongLegError = class extends PanopticError {
587
1346
  name = "NotALongLegError";
588
1347
  constructor(cause) {
589
- super("Cannot settle premium for non-long leg", cause);
1348
+ super("Cannot settle streamia for non-long leg", cause);
590
1349
  }
591
1350
  };
592
1351
  /**
@@ -4514,7 +5273,7 @@ function decodeAllLegs(tokenId) {
4514
5273
  const POOL_ID_MASK$2 = (1n << 64n) - 1n;
4515
5274
  const MAX_LEGS = TOKEN_ID_BITS.MAX_LEGS;
4516
5275
  const MAX_OPTION_RATIO = LEG_LIMITS.MAX_RATIO;
4517
- const Q192$4 = 1n << 192n;
5276
+ const Q192$3 = 1n << 192n;
4518
5277
 
4519
5278
  //#endregion
4520
5279
  //#region src/panoptic/v2/formatters/rates.ts
@@ -4526,7 +5285,7 @@ const SECONDS_PER_YEAR = SECONDS_PER_DAY * DAYS_PER_YEAR;
4526
5285
  //#region src/panoptic/v2/tokenId/generateOverlapping.ts
4527
5286
  const MAX_UINT64 = (1n << 64n) - 1n;
4528
5287
  const MAX_UINT128$2 = (1n << 128n) - 1n;
4529
- const Q192$3 = 1n << 192n;
5288
+ const Q192$2 = 1n << 192n;
4530
5289
 
4531
5290
  //#endregion
4532
5291
  //#region src/panoptic/v2/tokenId/split.ts
@@ -4536,7 +5295,7 @@ const MAX_UINT256 = (1n << 256n) - 1n;
4536
5295
 
4537
5296
  //#endregion
4538
5297
  //#region src/uniswap/lpDeposit.ts
4539
- const Q96$4 = 1n << 96n;
5298
+ const Q96$3 = 1n << 96n;
4540
5299
  const ceilDiv = (n, d) => (n + d - 1n) / d;
4541
5300
  /** Uniswap mint principal in raw token units, rounded up per leg, plus 5% headroom. */
4542
5301
  function getLpDepositAmounts(ranges, sqrtPriceX96) {
@@ -4552,8 +5311,8 @@ function getLpDepositBreakdown(ranges, sqrtPriceX96) {
4552
5311
  const lower = tickToSqrtPriceX96(BigInt(tickLower));
4553
5312
  const upper = tickToSqrtPriceX96(BigInt(tickUpper));
4554
5313
  const price = sqrtPriceX96 < lower ? lower : sqrtPriceX96 > upper ? upper : sqrtPriceX96;
4555
- amount0 += ceilDiv(liquidity * Q96$4 * (upper - price), upper * price);
4556
- amount1 += ceilDiv(liquidity * (price - lower), Q96$4);
5314
+ amount0 += ceilDiv(liquidity * Q96$3 * (upper - price), upper * price);
5315
+ amount1 += ceilDiv(liquidity * (price - lower), Q96$3);
4557
5316
  }
4558
5317
  const buffer = {
4559
5318
  amount0: ceilDiv(amount0 * 5n, 100n),
@@ -4581,7 +5340,7 @@ function getUnhedgedLpRanges({ tokenId, positionSize, tickSpacing }) {
4581
5340
  const lower = tickToSqrtPriceX96(tickLower);
4582
5341
  const upper = tickToSqrtPriceX96(tickUpper);
4583
5342
  const amount = positionSize * leg.optionRatio;
4584
- const liquidity = leg.asset === 0n ? amount * (lower * upper / Q96$4) / (upper - lower) : amount * Q96$4 / (upper - lower);
5343
+ const liquidity = leg.asset === 0n ? amount * (lower * upper / Q96$3) / (upper - lower) : amount * Q96$3 / (upper - lower);
4585
5344
  return liquidity <= 0n ? [] : [{
4586
5345
  tickLower: Number(tickLower),
4587
5346
  tickUpper: Number(tickUpper),
@@ -4602,7 +5361,7 @@ function getLpPositionFunding(params) {
4602
5361
  });
4603
5362
  const breakdown = getLpDepositBreakdown(ranges, sqrtPriceX96);
4604
5363
  const priceSquared = valuationSqrtPriceX96 * valuationSqrtPriceX96;
4605
- const value = ({ amount0, amount1 }) => quoteTokenIndex === 0 ? amount0 + ceilDiv(amount1 * Q96$4 * Q96$4, priceSquared) : amount1 + ceilDiv(amount0 * priceSquared, Q96$4 * Q96$4);
5364
+ const value = ({ amount0, amount1 }) => quoteTokenIndex === 0 ? amount0 + ceilDiv(amount1 * Q96$3 * Q96$3, priceSquared) : amount1 + ceilDiv(amount0 * priceSquared, Q96$3 * Q96$3);
4606
5365
  const principalInQuote = value(breakdown.principal);
4607
5366
  const totalInQuote = value(breakdown.total);
4608
5367
  return {
@@ -4632,8 +5391,8 @@ function getLpFundingDeposit({ funding, availableInQuote, minimumInQuote = 0n, q
4632
5391
  requiredInQuote,
4633
5392
  shortfallInQuote,
4634
5393
  defaultQuotePercent,
4635
- amount0: quoteTokenIndex === 0 ? quoteAmount : ceilDiv(assetValue * Q96$4 * Q96$4, priceSquared),
4636
- amount1: quoteTokenIndex === 1 ? quoteAmount : ceilDiv(assetValue * priceSquared, Q96$4 * Q96$4)
5394
+ amount0: quoteTokenIndex === 0 ? quoteAmount : ceilDiv(assetValue * Q96$3 * Q96$3, priceSquared),
5395
+ amount1: quoteTokenIndex === 1 ? quoteAmount : ceilDiv(assetValue * priceSquared, Q96$3 * Q96$3)
4637
5396
  };
4638
5397
  }
4639
5398
  /** Largest raw size funded by available collateral, including native-token rounding. */
@@ -4655,66 +5414,6 @@ function getMaxLpPositionSize(params) {
4655
5414
  return low;
4656
5415
  }
4657
5416
 
4658
- //#endregion
4659
- //#region src/uniswap/lpGreeks.ts
4660
- const Q96$3 = 1n << 96n;
4661
- const Q192$2 = 1n << 192n;
4662
- /**
4663
- * Compute the token0/token1 amounts backing `liquidity` over `[sqrtA, sqrtB]`
4664
- * at the current price `sqrtP`, mirroring Uniswap's `LiquidityAmounts`
4665
- * (`getAmountsForLiquidity`). All sqrt prices are X96. The current price is
4666
- * clamped into the range, so out-of-range positions collapse to a single token.
4667
- */
4668
- function getAmountsForLiquidity(sqrtPriceX96, sqrtRatioAX96, sqrtRatioBX96, liquidity) {
4669
- const [sqrtA, sqrtB] = sqrtRatioAX96 <= sqrtRatioBX96 ? [sqrtRatioAX96, sqrtRatioBX96] : [sqrtRatioBX96, sqrtRatioAX96];
4670
- const sqrtC = sqrtPriceX96 < sqrtA ? sqrtA : sqrtPriceX96 > sqrtB ? sqrtB : sqrtPriceX96;
4671
- const amount0 = sqrtC < sqrtB ? liquidity * (sqrtB - sqrtC) * Q96$3 / (sqrtC * sqrtB) : 0n;
4672
- const amount1 = sqrtC > sqrtA ? liquidity * (sqrtC - sqrtA) / Q96$3 : 0n;
4673
- return {
4674
- amount0,
4675
- amount1
4676
- };
4677
- }
4678
- /**
4679
- * Greeks (value, delta, gamma) for a Uniswap LP position in the chosen asset
4680
- * frame. See the module docs for the unit conventions.
4681
- *
4682
- * Closed forms (in-range, numeraire = token1 / asset = token0):
4683
- * value = amount1 + amount0·P (P = sqrtP² / 2^192)
4684
- * delta = amount0 (= dV/dP)
4685
- * gamma = P²·d²V/dP² = -L·sqrt(P)/2 (short gamma)
4686
- * The `assetIndex = 1` frame is the symmetric inverse (numeraire = token0).
4687
- * Gamma is zero when the price is outside the range (no curvature there).
4688
- */
4689
- function getLpGreeks(input) {
4690
- const { liquidity, tickLower, tickUpper, currentTick, assetIndex } = input;
4691
- const sqrtP = input.sqrtPriceX96 ?? tickToSqrtPriceX96(currentTick);
4692
- if (sqrtP <= 0n) throw new RangeError("Invalid sqrt price");
4693
- const sqrtA = tickToSqrtPriceX96(tickLower);
4694
- const sqrtB = tickToSqrtPriceX96(tickUpper);
4695
- const { amount0, amount1 } = getAmountsForLiquidity(sqrtP, sqrtA, sqrtB, liquidity);
4696
- const sqrtP2 = sqrtP * sqrtP;
4697
- const inRange = sqrtP > sqrtA && sqrtP < sqrtB;
4698
- if (assetIndex === 0) {
4699
- const value$1 = amount1 + amount0 * sqrtP2 / Q192$2;
4700
- const delta$1 = amount0;
4701
- const gamma$1 = inRange ? -(liquidity * sqrtP) / (2n * Q96$3) : 0n;
4702
- return {
4703
- value: value$1,
4704
- delta: delta$1,
4705
- gamma: gamma$1
4706
- };
4707
- }
4708
- const value = amount0 + amount1 * Q192$2 / sqrtP2;
4709
- const delta = amount1;
4710
- const gamma = inRange ? -(liquidity * Q96$3) / (2n * sqrtP) : 0n;
4711
- return {
4712
- value,
4713
- delta,
4714
- gamma
4715
- };
4716
- }
4717
-
4718
5417
  //#endregion
4719
5418
  //#region src/uniswap/lpFeeReturn.ts
4720
5419
  const D = Decimal.clone({ precision: 60 });
@@ -4756,6 +5455,146 @@ function getLpFeeReturnSeries({ points, ranges, startTick }) {
4756
5455
  });
4757
5456
  }
4758
5457
 
5458
+ //#endregion
5459
+ //#region src/uniswap/lpHistory.ts
5460
+ const unsigned = z.string().regex(/^\d+$/).transform(BigInt);
5461
+ const eventFields = {
5462
+ id: z.string().min(1),
5463
+ hash: z.string().regex(/^0x[0-9a-fA-F]{64}$/),
5464
+ blockNumber: unsigned,
5465
+ logIndex: unsigned,
5466
+ timestamp: unsigned,
5467
+ amount0: unsigned,
5468
+ amount1: unsigned
5469
+ };
5470
+ const changeSchema = z.object({
5471
+ ...eventFields,
5472
+ eventType: z.enum(["Mint", "Burn"]),
5473
+ liquidity: unsigned,
5474
+ amountSource: z.string().nullable()
5475
+ });
5476
+ const collectSchema = z.object({
5477
+ ...eventFields,
5478
+ recipient: z.string().regex(/^0x[0-9a-fA-F]{40}$/)
5479
+ });
5480
+ const pageSchema = z.object({
5481
+ _meta: z.object({
5482
+ block: z.object({
5483
+ number: z.number().int().nonnegative(),
5484
+ hash: z.string().regex(/^0x[0-9a-fA-F]{64}$/)
5485
+ }),
5486
+ hasIndexingErrors: z.boolean()
5487
+ }),
5488
+ uniswapLpPosition: z.object({
5489
+ version: z.union([z.literal(3), z.literal(4)]),
5490
+ liquidity: unsigned,
5491
+ liquidityChanges: z.array(changeSchema),
5492
+ collects: z.array(collectSchema)
5493
+ }).nullable()
5494
+ });
5495
+ const HISTORY_QUERY = `
5496
+ query LpPositionActivity($positionId: ID!, $block: Block_height, $changeCursor: ID!, $collectCursor: ID!, $pageSize: Int!) {
5497
+ _meta(block: $block) { block { number hash } hasIndexingErrors }
5498
+ uniswapLpPosition(id: $positionId, block: $block) {
5499
+ version
5500
+ liquidity
5501
+ liquidityChanges(first: $pageSize, where: { id_gt: $changeCursor }, orderBy: id, orderDirection: asc) {
5502
+ id hash eventType liquidity amount0 amount1 amountSource blockNumber logIndex timestamp
5503
+ }
5504
+ collects(first: $pageSize, where: { id_gt: $collectCursor }, orderBy: id, orderDirection: asc) {
5505
+ id hash amount0 amount1 blockNumber logIndex timestamp recipient
5506
+ }
5507
+ }
5508
+ }
5509
+ `;
5510
+ /** Complete NFT activity at one indexed block, sorted by block and log index. */
5511
+ async function getLpPositionHistory({ url, positionId, signal }) {
5512
+ if (!/^v[34]-\d+$/.test(positionId)) throw new RangeError("Invalid LP position id");
5513
+ const client = new GraphQLClient(url, { signal });
5514
+ const events = [];
5515
+ let block = null;
5516
+ let changeCursor = "";
5517
+ let collectCursor = "";
5518
+ while (true) {
5519
+ const page = pageSchema.parse(await client.request(HISTORY_QUERY, {
5520
+ positionId,
5521
+ block,
5522
+ changeCursor,
5523
+ collectCursor,
5524
+ pageSize: 1e3
5525
+ }));
5526
+ if (page._meta.hasIndexingErrors) throw new Error("LP history indexing is incomplete");
5527
+ const position = page.uniswapLpPosition;
5528
+ if (!position) throw new Error("LP position history is unavailable");
5529
+ if (position.version !== Number(positionId[1])) throw new Error("LP position version mismatch");
5530
+ if (block && block.hash !== page._meta.block.hash) throw new Error("LP history checkpoint changed");
5531
+ block = { hash: page._meta.block.hash };
5532
+ const changes = position.liquidityChanges;
5533
+ const collects = position.collects;
5534
+ events.push(...changes, ...collects.map((event) => ({
5535
+ ...event,
5536
+ eventType: "Collect",
5537
+ amountSource: "ExactEvent"
5538
+ })));
5539
+ const lastChange = changes.at(-1);
5540
+ const lastCollect = collects.at(-1);
5541
+ if (lastChange && lastChange.id <= changeCursor || lastCollect && lastCollect.id <= collectCursor) throw new Error("LP history pagination did not advance");
5542
+ changeCursor = lastChange?.id ?? changeCursor;
5543
+ collectCursor = lastCollect?.id ?? collectCursor;
5544
+ if (changes.length < 1e3 && collects.length < 1e3) {
5545
+ events.sort((a, b) => {
5546
+ const order = a.blockNumber - b.blockNumber || a.logIndex - b.logIndex;
5547
+ return order < 0n ? -1 : order > 0n ? 1 : 0;
5548
+ });
5549
+ let held = 0n;
5550
+ for (const event of events) {
5551
+ if (event.eventType === "Collect") continue;
5552
+ held += event.eventType === "Burn" ? -event.liquidity : event.liquidity;
5553
+ if (held < 0n) throw new Error("LP liquidity history is incomplete");
5554
+ }
5555
+ if (held !== position.liquidity || events.length === 0) throw new Error("LP liquidity history is incomplete");
5556
+ return {
5557
+ events,
5558
+ positionId,
5559
+ blockHash: page._meta.block.hash,
5560
+ blockNumber: BigInt(page._meta.block.number),
5561
+ version: position.version
5562
+ };
5563
+ }
5564
+ }
5565
+ }
5566
+ /** Token flows; v3 collects may include principal already recorded in removals. */
5567
+ function summarizeLpPositionHistory(events) {
5568
+ const totals = (eventType) => {
5569
+ let amount0 = 0n;
5570
+ let amount1 = 0n;
5571
+ let estimated = false;
5572
+ for (const event of events) {
5573
+ if (event.eventType !== eventType) continue;
5574
+ if (event.amountSource !== "ExactEvent" && event.amountSource !== "ExactSameTxSwap") {
5575
+ if (event.amountSource !== "ApproxExtsload") return {
5576
+ amount0: null,
5577
+ amount1: null,
5578
+ estimated: false
5579
+ };
5580
+ estimated = true;
5581
+ }
5582
+ amount0 += event.amount0;
5583
+ amount1 += event.amount1;
5584
+ }
5585
+ return {
5586
+ amount0,
5587
+ amount1,
5588
+ estimated
5589
+ };
5590
+ };
5591
+ return {
5592
+ added: totals("Mint"),
5593
+ removed: totals("Burn"),
5594
+ collected: totals("Collect")
5595
+ };
5596
+ }
5597
+
4759
5598
  //#endregion
4760
5599
  //#region src/panoptic/v2/greeks/positionVolatility.ts
4761
5600
  const Precision$1 = Decimal.clone({ precision: 80 });
@@ -4842,11 +5681,13 @@ function valuePositionAccrual({ snapshots, quoteIsToken0, quoteDecimals }) {
4842
5681
  const Precision = Decimal.clone({ precision: 80 });
4843
5682
  const Q192$1 = (1n << 192n).toString();
4844
5683
  /** Historical convexity and fee coverage at constant LP liquidity, in human quote units. */
4845
- function calculateLpPositionVolatility({ liquidity, tickLower, tickUpper, quoteIsToken0, quoteDecimals, snapshots }) {
5684
+ function calculateLpPositionVolatility({ liquidity, tickLower, tickUpper, quoteIsToken0, quoteDecimals, snapshots, observations: priceObservations }) {
4846
5685
  if (liquidity <= 0n || liquidity >= 1n << 128n) throw new RangeError("Invalid LP liquidity");
4847
5686
  if (tickLower < -887272n || tickUpper > 887272n || tickLower >= tickUpper) throw new RangeError("Invalid LP range");
5687
+ if (snapshots.some((point, index) => index > 0 && point.blockTimestamp <= snapshots[index - 1].blockTimestamp)) throw new RangeError("Fee snapshots must have increasing timestamps");
4848
5688
  const scale = new Decimal(10).pow(quoteDecimals);
4849
- const observations = snapshots.map((snapshot) => ({
5689
+ if (priceObservations && (priceObservations.length < 2 || priceObservations[0].timestamp !== snapshots[0]?.blockTimestamp || priceObservations.at(-1)?.timestamp !== snapshots.at(-1)?.blockTimestamp)) throw new RangeError("Price and fee history must cover the same window");
5690
+ const observations = priceObservations ?? snapshots.map((snapshot) => ({
4850
5691
  timestamp: snapshot.blockTimestamp,
4851
5692
  price: quoteIsToken0 ? new Precision(Q192$1).div(new Precision(snapshot.sqrtPriceX96.toString()).pow(2)) : new Precision(snapshot.sqrtPriceX96.toString()).pow(2).div(Q192$1),
4852
5693
  gamma: new Decimal(getLpGreeks({
@@ -4934,10 +5775,10 @@ function quoteTokenPrices(pools, quoteAddresses) {
4934
5775
  */
4935
5776
  function normalCdf(x) {
4936
5777
  if (!Number.isFinite(x)) return x > 0 ? 1 : 0;
4937
- const z = x / Math.SQRT2;
4938
- const t = 1 / (1 + .3275911 * Math.abs(z));
4939
- const y = 1 - ((((1.061405429 * t - 1.453152027) * t + 1.421413741) * t - .284496736) * t + .254829592) * t * Math.exp(-z * z);
4940
- const erf = z >= 0 ? y : -y;
5778
+ const z$1 = x / Math.SQRT2;
5779
+ const t = 1 / (1 + .3275911 * Math.abs(z$1));
5780
+ const y = 1 - ((((1.061405429 * t - 1.453152027) * t + 1.421413741) * t - .284496736) * t + .254829592) * t * Math.exp(-z$1 * z$1);
5781
+ const erf = z$1 >= 0 ? y : -y;
4941
5782
  return .5 * (1 + erf);
4942
5783
  }
4943
5784
  /**
@@ -5168,104 +6009,21 @@ const V3_SWAP_EXACT_IN = 0;
5168
6009
  const V3_SWAP_EXACT_OUT = 1;
5169
6010
  /**
5170
6011
  * Universal Router recipient sentinel: the router maps `address(1)` to
5171
- * `msg.sender` (the `execute` caller). Uniswap `Constants.MSG_SENDER`.
5172
- */
5173
- const MSG_SENDER = "0x0000000000000000000000000000000000000001";
5174
- const UINT128_MAX$4 = (1n << 128n) - 1n;
5175
- const v3ExactInInputAbi = [
5176
- {
5177
- name: "recipient",
5178
- type: "address"
5179
- },
5180
- {
5181
- name: "amountIn",
5182
- type: "uint256"
5183
- },
5184
- {
5185
- name: "amountOutMinimum",
5186
- type: "uint256"
5187
- },
5188
- {
5189
- name: "path",
5190
- type: "bytes"
5191
- },
5192
- {
5193
- name: "payerIsUser",
5194
- type: "bool"
5195
- }
5196
- ];
5197
- function assertUint128$1(amount) {
5198
- if (amount < 0n || amount > UINT128_MAX$4) throw new AmountExceedsUint128Error(amount);
5199
- }
5200
- /**
5201
- * Encode the packed v3 single-hop path `tokenIn ++ fee(uint24) ++ tokenOut`.
5202
- */
5203
- function encodeV3Path(tokenIn, fee, tokenOut) {
5204
- if (fee < 0n || fee > 0xffffffn) throw new PanopticError(`v3 fee ${fee} exceeds uint24`);
5205
- return encodePacked([
5206
- "address",
5207
- "uint24",
5208
- "address"
5209
- ], [
5210
- tokenIn,
5211
- Number(fee),
5212
- tokenOut
5213
- ]);
5214
- }
5215
- /**
5216
- * Build the typed `execute(...)` args for an exact-in single-hop v3 swap whose
5217
- * output is delivered to the `execute` caller (recipient = MSG_SENDER).
5218
- */
5219
- function buildV3SwapExecuteArgs(args) {
5220
- const { tokenIn, tokenOut, fee, amountIn, amountOutMinimum, deadline } = args;
5221
- if (tokenIn === zeroAddress || tokenOut === zeroAddress) throw new PanopticError("native ETH is not supported by the v3 exact-in router builder");
5222
- assertUint128$1(amountIn);
5223
- assertUint128$1(amountOutMinimum);
5224
- const path = encodeV3Path(tokenIn, fee, tokenOut);
5225
- const input = encodeAbiParameters(v3ExactInInputAbi, [
5226
- MSG_SENDER,
5227
- amountIn,
5228
- amountOutMinimum,
5229
- path,
5230
- true
5231
- ]);
5232
- const commands = encodePacked(["uint8"], [V3_SWAP_EXACT_IN]);
5233
- return {
5234
- args: [
5235
- commands,
5236
- [input],
5237
- deadline
5238
- ],
5239
- value: 0n
5240
- };
5241
- }
5242
- /**
5243
- * Build the `execute(commands, inputs, deadline)` calldata for an exact-in
5244
- * single-hop v3 swap.
5245
- */
5246
- function buildV3SwapExecuteCalldata(args) {
5247
- const { args: executeArgs, value } = buildV3SwapExecuteArgs(args);
5248
- const data = encodeFunctionData({
5249
- abi: universalRouterAbi,
5250
- functionName: "execute",
5251
- args: executeArgs
5252
- });
5253
- return {
5254
- data,
5255
- value
5256
- };
5257
- }
5258
- const v3ExactOutInputAbi = [
6012
+ * `msg.sender` (the `execute` caller). Uniswap `Constants.MSG_SENDER`.
6013
+ */
6014
+ const MSG_SENDER = "0x0000000000000000000000000000000000000001";
6015
+ const UINT128_MAX$4 = (1n << 128n) - 1n;
6016
+ const v3ExactInInputAbi = [
5259
6017
  {
5260
6018
  name: "recipient",
5261
6019
  type: "address"
5262
6020
  },
5263
6021
  {
5264
- name: "amountOut",
6022
+ name: "amountIn",
5265
6023
  type: "uint256"
5266
6024
  },
5267
6025
  {
5268
- name: "amountInMaximum",
6026
+ name: "amountOutMinimum",
5269
6027
  type: "uint256"
5270
6028
  },
5271
6029
  {
@@ -5277,547 +6035,316 @@ const v3ExactOutInputAbi = [
5277
6035
  type: "bool"
5278
6036
  }
5279
6037
  ];
6038
+ function assertUint128$1(amount) {
6039
+ if (amount < 0n || amount > UINT128_MAX$4) throw new AmountExceedsUint128Error(amount);
6040
+ }
5280
6041
  /**
5281
- * Build the typed `execute(...)` args for an exact-out single-hop v3 swap.
5282
- * The v3 exact-out path is reversed: `tokenOut ++ fee ++ tokenIn`.
6042
+ * Encode the packed v3 single-hop path `tokenIn ++ fee(uint24) ++ tokenOut`.
5283
6043
  */
5284
- function buildV3ExactOutSwapExecuteArgs(args) {
5285
- const { tokenIn, tokenOut, fee, amountOut, amountInMaximum, deadline } = args;
5286
- if (tokenIn === zeroAddress || tokenOut === zeroAddress) throw new PanopticError("native ETH is not supported by the v3 exact-out router builder");
5287
- assertUint128$1(amountOut);
5288
- assertUint128$1(amountInMaximum);
5289
- const path = encodeV3Path(tokenOut, fee, tokenIn);
5290
- const input = encodeAbiParameters(v3ExactOutInputAbi, [
6044
+ function encodeV3Path(tokenIn, fee, tokenOut) {
6045
+ if (fee < 0n || fee > 0xffffffn) throw new PanopticError(`v3 fee ${fee} exceeds uint24`);
6046
+ return encodePacked([
6047
+ "address",
6048
+ "uint24",
6049
+ "address"
6050
+ ], [
6051
+ tokenIn,
6052
+ Number(fee),
6053
+ tokenOut
6054
+ ]);
6055
+ }
6056
+ /**
6057
+ * Build the typed `execute(...)` args for an exact-in single-hop v3 swap whose
6058
+ * output is delivered to the `execute` caller (recipient = MSG_SENDER).
6059
+ */
6060
+ function buildV3SwapExecuteArgs(args) {
6061
+ const { tokenIn, tokenOut, fee, amountIn, amountOutMinimum, deadline } = args;
6062
+ if (tokenIn === zeroAddress || tokenOut === zeroAddress) throw new PanopticError("native ETH is not supported by the v3 exact-in router builder");
6063
+ assertUint128$1(amountIn);
6064
+ assertUint128$1(amountOutMinimum);
6065
+ const path = encodeV3Path(tokenIn, fee, tokenOut);
6066
+ const input = encodeAbiParameters(v3ExactInInputAbi, [
5291
6067
  MSG_SENDER,
5292
- amountOut,
5293
- amountInMaximum,
6068
+ amountIn,
6069
+ amountOutMinimum,
5294
6070
  path,
5295
6071
  true
5296
6072
  ]);
5297
- const commands = encodePacked(["uint8"], [V3_SWAP_EXACT_OUT]);
6073
+ const commands = encodePacked(["uint8"], [V3_SWAP_EXACT_IN]);
5298
6074
  return {
5299
6075
  args: [
5300
6076
  commands,
5301
- [input],
5302
- deadline
5303
- ],
5304
- value: 0n
5305
- };
5306
- }
5307
- function buildV3ExactOutSwapExecuteCalldata(args) {
5308
- const { args: executeArgs, value } = buildV3ExactOutSwapExecuteArgs(args);
5309
- const data = encodeFunctionData({
5310
- abi: universalRouterAbi,
5311
- functionName: "execute",
5312
- args: executeArgs
5313
- });
5314
- return {
5315
- data,
5316
- value
5317
- };
5318
- }
5319
-
5320
- //#endregion
5321
- //#region src/uniswap/v3/abis/quoterV2.ts
5322
- /**
5323
- * Minimal Uniswap v3 QuoterV2 ABI.
5324
- *
5325
- * QuoterV2 is revert/staticcall-based (nonpayable but intended for `eth_call` /
5326
- * `simulateContract`), so it must be simulated, not read.
5327
- * @module uniswap/v3/abis/quoterV2
5328
- */
5329
- const quoterV2Abi = [{
5330
- type: "function",
5331
- name: "quoteExactInputSingle",
5332
- stateMutability: "nonpayable",
5333
- inputs: [{
5334
- name: "params",
5335
- type: "tuple",
5336
- components: [
5337
- {
5338
- name: "tokenIn",
5339
- type: "address"
5340
- },
5341
- {
5342
- name: "tokenOut",
5343
- type: "address"
5344
- },
5345
- {
5346
- name: "amountIn",
5347
- type: "uint256"
5348
- },
5349
- {
5350
- name: "fee",
5351
- type: "uint24"
5352
- },
5353
- {
5354
- name: "sqrtPriceLimitX96",
5355
- type: "uint160"
5356
- }
5357
- ]
5358
- }],
5359
- outputs: [
5360
- {
5361
- name: "amountOut",
5362
- type: "uint256"
5363
- },
5364
- {
5365
- name: "sqrtPriceX96After",
5366
- type: "uint160"
5367
- },
5368
- {
5369
- name: "initializedTicksCrossed",
5370
- type: "uint32"
5371
- },
5372
- {
5373
- name: "gasEstimate",
5374
- type: "uint256"
5375
- }
5376
- ]
5377
- }, {
5378
- type: "function",
5379
- name: "quoteExactOutputSingle",
5380
- stateMutability: "nonpayable",
5381
- inputs: [{
5382
- name: "params",
5383
- type: "tuple",
5384
- components: [
5385
- {
5386
- name: "tokenIn",
5387
- type: "address"
5388
- },
5389
- {
5390
- name: "tokenOut",
5391
- type: "address"
5392
- },
5393
- {
5394
- name: "amount",
5395
- type: "uint256"
5396
- },
5397
- {
5398
- name: "fee",
5399
- type: "uint24"
5400
- },
5401
- {
5402
- name: "sqrtPriceLimitX96",
5403
- type: "uint160"
5404
- }
5405
- ]
5406
- }],
5407
- outputs: [
5408
- {
5409
- name: "amountIn",
5410
- type: "uint256"
5411
- },
5412
- {
5413
- name: "sqrtPriceX96After",
5414
- type: "uint160"
5415
- },
5416
- {
5417
- name: "initializedTicksCrossed",
5418
- type: "uint32"
5419
- },
5420
- {
5421
- name: "gasEstimate",
5422
- type: "uint256"
5423
- }
5424
- ]
5425
- }];
5426
-
5427
- //#endregion
5428
- //#region src/uniswap/v3/router/quote.ts
5429
- const BPS_DENOMINATOR$2 = 10000n;
5430
- const UINT128_MAX$3 = (1n << 128n) - 1n;
5431
- /**
5432
- * Quote an exact-in v3 swap. Returns `null` when the quote reverts (e.g. the
5433
- * pool does not exist / has no liquidity) so callers can skip that pool when
5434
- * ranking venues, rather than aborting the whole cycle.
5435
- */
5436
- async function quoteV3ExactIn(params) {
5437
- const { client, chainId, tokenIn, tokenOut, fee, amountIn, slippageBps, blockNumber } = params;
5438
- if (amountIn < 0n || amountIn > UINT128_MAX$3) throw new PanopticError(`amountIn ${amountIn} exceeds uint128 maximum`);
5439
- assertSlippageBps$1(slippageBps);
5440
- const { quoterV2 } = getUniswapV3Addresses(chainId, params.addresses);
5441
- try {
5442
- const { result } = await client.simulateContract({
5443
- address: quoterV2,
5444
- abi: quoterV2Abi,
5445
- functionName: "quoteExactInputSingle",
5446
- blockNumber,
5447
- args: [{
5448
- tokenIn,
5449
- tokenOut,
5450
- amountIn,
5451
- fee: Number(fee),
5452
- sqrtPriceLimitX96: 0n
5453
- }]
5454
- });
5455
- const [amountOut, , , gasEstimate] = result;
5456
- const amountOutMinimum = amountOut * (BPS_DENOMINATOR$2 - slippageBps) / BPS_DENOMINATOR$2;
5457
- return {
5458
- amountOut,
5459
- amountOutMinimum,
5460
- gasEstimate
5461
- };
5462
- } catch (err) {
5463
- if (isRevert$1(err)) return null;
5464
- throw err;
5465
- }
5466
- }
5467
- /**
5468
- * Quote an exact-out v3 swap. Returns `null` on revert (no pool / no liquidity).
5469
- */
5470
- async function quoteV3ExactOut(params) {
5471
- const { client, chainId, tokenIn, tokenOut, fee, amountOut, slippageBps, blockNumber } = params;
5472
- if (amountOut < 0n || amountOut > UINT128_MAX$3) throw new PanopticError(`amountOut ${amountOut} exceeds uint128 maximum`);
5473
- assertSlippageBps$1(slippageBps);
5474
- const { quoterV2 } = getUniswapV3Addresses(chainId, params.addresses);
5475
- try {
5476
- const { result } = await client.simulateContract({
5477
- address: quoterV2,
5478
- abi: quoterV2Abi,
5479
- functionName: "quoteExactOutputSingle",
5480
- blockNumber,
5481
- args: [{
5482
- tokenIn,
5483
- tokenOut,
5484
- amount: amountOut,
5485
- fee: Number(fee),
5486
- sqrtPriceLimitX96: 0n
5487
- }]
5488
- });
5489
- const [amountIn, , , gasEstimate] = result;
5490
- const amountInMaximum = (amountIn * (BPS_DENOMINATOR$2 + slippageBps) + BPS_DENOMINATOR$2 - 1n) / BPS_DENOMINATOR$2;
5491
- return {
5492
- amountIn,
5493
- amountInMaximum,
5494
- gasEstimate
5495
- };
5496
- } catch (err) {
5497
- if (isRevert$1(err)) return null;
5498
- throw err;
5499
- }
5500
- }
5501
- function assertSlippageBps$1(slippageBps) {
5502
- if (slippageBps < 0n || slippageBps > BPS_DENOMINATOR$2) throw new PanopticError(`invalid slippageBps ${slippageBps}, must be 0..10000`);
5503
- }
5504
- function isRevert$1(err) {
5505
- return err instanceof BaseError && err.walk((e) => e instanceof ContractFunctionRevertedError) instanceof ContractFunctionRevertedError;
6077
+ [input],
6078
+ deadline
6079
+ ],
6080
+ value: 0n
6081
+ };
5506
6082
  }
5507
-
5508
- //#endregion
5509
- //#region src/panoptic/v2/clients/blockMeta.ts
5510
6083
  /**
5511
- * Get block metadata for a given block.
5512
- * Used to tag all read results with same-block consistency proof.
5513
- *
5514
- * @param params - The parameters
5515
- * @returns Block metadata
6084
+ * Build the `execute(commands, inputs, deadline)` calldata for an exact-in
6085
+ * single-hop v3 swap.
5516
6086
  */
5517
- async function getBlockMeta(params) {
5518
- const { client, blockNumber } = params;
5519
- const block = await client.getBlock({
5520
- blockNumber,
5521
- includeTransactions: false
6087
+ function buildV3SwapExecuteCalldata(args) {
6088
+ const { args: executeArgs, value } = buildV3SwapExecuteArgs(args);
6089
+ const data = encodeFunctionData({
6090
+ abi: universalRouterAbi,
6091
+ functionName: "execute",
6092
+ args: executeArgs
5522
6093
  });
5523
6094
  return {
5524
- blockNumber: block.number,
5525
- blockHash: block.hash,
5526
- blockTimestamp: block.timestamp
6095
+ data,
6096
+ value
5527
6097
  };
5528
6098
  }
5529
-
5530
- //#endregion
5531
- //#region src/panoptic/v2/abis/stateView.ts
5532
- /**
5533
- * Minimal Uniswap V4 StateView ABI for fee growth reads.
5534
- * Only includes functions needed by streamia history.
5535
- */
5536
- const stateViewAbi = [
6099
+ const v3ExactOutInputAbi = [
5537
6100
  {
5538
- inputs: [{
5539
- internalType: "PoolId",
5540
- name: "poolId",
5541
- type: "bytes32"
5542
- }],
5543
- name: "getSlot0",
5544
- outputs: [
5545
- {
5546
- internalType: "uint160",
5547
- name: "sqrtPriceX96",
5548
- type: "uint160"
5549
- },
5550
- {
5551
- internalType: "int24",
5552
- name: "tick",
5553
- type: "int24"
5554
- },
5555
- {
5556
- internalType: "uint24",
5557
- name: "protocolFee",
5558
- type: "uint24"
5559
- },
5560
- {
5561
- internalType: "uint24",
5562
- name: "lpFee",
5563
- type: "uint24"
5564
- }
5565
- ],
5566
- stateMutability: "view",
5567
- type: "function"
6101
+ name: "recipient",
6102
+ type: "address"
5568
6103
  },
5569
6104
  {
5570
- inputs: [{
5571
- internalType: "PoolId",
5572
- name: "poolId",
5573
- type: "bytes32"
5574
- }],
5575
- name: "getFeeGrowthGlobals",
5576
- outputs: [{
5577
- internalType: "uint256",
5578
- name: "feeGrowthGlobal0",
5579
- type: "uint256"
5580
- }, {
5581
- internalType: "uint256",
5582
- name: "feeGrowthGlobal1",
5583
- type: "uint256"
5584
- }],
5585
- stateMutability: "view",
5586
- type: "function"
6105
+ name: "amountOut",
6106
+ type: "uint256"
5587
6107
  },
5588
6108
  {
5589
- inputs: [{
5590
- internalType: "PoolId",
5591
- name: "poolId",
5592
- type: "bytes32"
5593
- }, {
5594
- internalType: "int24",
5595
- name: "tick",
5596
- type: "int24"
5597
- }],
5598
- name: "getTickInfo",
5599
- outputs: [
5600
- {
5601
- internalType: "uint128",
5602
- name: "liquidityGross",
5603
- type: "uint128"
5604
- },
5605
- {
5606
- internalType: "int128",
5607
- name: "liquidityNet",
5608
- type: "int128"
5609
- },
5610
- {
5611
- internalType: "uint256",
5612
- name: "feeGrowthOutside0X128",
5613
- type: "uint256"
5614
- },
5615
- {
5616
- internalType: "uint256",
5617
- name: "feeGrowthOutside1X128",
5618
- type: "uint256"
5619
- }
5620
- ],
5621
- stateMutability: "view",
5622
- type: "function"
6109
+ name: "amountInMaximum",
6110
+ type: "uint256"
5623
6111
  },
5624
6112
  {
5625
- inputs: [{
5626
- internalType: "PoolId",
5627
- name: "poolId",
5628
- type: "bytes32"
5629
- }],
5630
- name: "getLiquidity",
5631
- outputs: [{
5632
- internalType: "uint128",
5633
- name: "liquidity",
5634
- type: "uint128"
5635
- }],
5636
- stateMutability: "view",
5637
- type: "function"
6113
+ name: "path",
6114
+ type: "bytes"
6115
+ },
6116
+ {
6117
+ name: "payerIsUser",
6118
+ type: "bool"
5638
6119
  }
5639
6120
  ];
5640
-
5641
- //#endregion
5642
- //#region src/panoptic/v2/abis/uniswapV3Pool.ts
5643
6121
  /**
5644
- * Minimal Uniswap V3 Pool ABI for fee growth reads.
5645
- * Only includes functions needed by streamia history.
6122
+ * Build the typed `execute(...)` args for an exact-out single-hop v3 swap.
6123
+ * The v3 exact-out path is reversed: `tokenOut ++ fee ++ tokenIn`.
5646
6124
  */
5647
- const uniswapV3PoolAbi = [
5648
- {
5649
- inputs: [],
5650
- name: "slot0",
5651
- outputs: [
5652
- {
5653
- internalType: "uint160",
5654
- name: "sqrtPriceX96",
5655
- type: "uint160"
5656
- },
5657
- {
5658
- internalType: "int24",
5659
- name: "tick",
5660
- type: "int24"
5661
- },
5662
- {
5663
- internalType: "uint16",
5664
- name: "observationIndex",
5665
- type: "uint16"
5666
- },
5667
- {
5668
- internalType: "uint16",
5669
- name: "observationCardinality",
5670
- type: "uint16"
5671
- },
5672
- {
5673
- internalType: "uint16",
5674
- name: "observationCardinalityNext",
5675
- type: "uint16"
5676
- },
5677
- {
5678
- internalType: "uint8",
5679
- name: "feeProtocol",
5680
- type: "uint8"
5681
- },
5682
- {
5683
- internalType: "bool",
5684
- name: "unlocked",
5685
- type: "bool"
5686
- }
6125
+ function buildV3ExactOutSwapExecuteArgs(args) {
6126
+ const { tokenIn, tokenOut, fee, amountOut, amountInMaximum, deadline } = args;
6127
+ if (tokenIn === zeroAddress || tokenOut === zeroAddress) throw new PanopticError("native ETH is not supported by the v3 exact-out router builder");
6128
+ assertUint128$1(amountOut);
6129
+ assertUint128$1(amountInMaximum);
6130
+ const path = encodeV3Path(tokenOut, fee, tokenIn);
6131
+ const input = encodeAbiParameters(v3ExactOutInputAbi, [
6132
+ MSG_SENDER,
6133
+ amountOut,
6134
+ amountInMaximum,
6135
+ path,
6136
+ true
6137
+ ]);
6138
+ const commands = encodePacked(["uint8"], [V3_SWAP_EXACT_OUT]);
6139
+ return {
6140
+ args: [
6141
+ commands,
6142
+ [input],
6143
+ deadline
5687
6144
  ],
5688
- stateMutability: "view",
5689
- type: "function"
5690
- },
5691
- {
5692
- inputs: [],
5693
- name: "feeGrowthGlobal0X128",
5694
- outputs: [{
5695
- internalType: "uint256",
5696
- name: "",
5697
- type: "uint256"
5698
- }],
5699
- stateMutability: "view",
5700
- type: "function"
5701
- },
5702
- {
5703
- inputs: [],
5704
- name: "feeGrowthGlobal1X128",
5705
- outputs: [{
5706
- internalType: "uint256",
5707
- name: "",
5708
- type: "uint256"
5709
- }],
5710
- stateMutability: "view",
5711
- type: "function"
5712
- },
5713
- {
5714
- inputs: [{
5715
- internalType: "int24",
5716
- name: "",
5717
- type: "int24"
5718
- }],
5719
- name: "ticks",
5720
- outputs: [
6145
+ value: 0n
6146
+ };
6147
+ }
6148
+ function buildV3ExactOutSwapExecuteCalldata(args) {
6149
+ const { args: executeArgs, value } = buildV3ExactOutSwapExecuteArgs(args);
6150
+ const data = encodeFunctionData({
6151
+ abi: universalRouterAbi,
6152
+ functionName: "execute",
6153
+ args: executeArgs
6154
+ });
6155
+ return {
6156
+ data,
6157
+ value
6158
+ };
6159
+ }
6160
+
6161
+ //#endregion
6162
+ //#region src/uniswap/v3/abis/quoterV2.ts
6163
+ /**
6164
+ * Minimal Uniswap v3 QuoterV2 ABI.
6165
+ *
6166
+ * QuoterV2 is revert/staticcall-based (nonpayable but intended for `eth_call` /
6167
+ * `simulateContract`), so it must be simulated, not read.
6168
+ * @module uniswap/v3/abis/quoterV2
6169
+ */
6170
+ const quoterV2Abi = [{
6171
+ type: "function",
6172
+ name: "quoteExactInputSingle",
6173
+ stateMutability: "nonpayable",
6174
+ inputs: [{
6175
+ name: "params",
6176
+ type: "tuple",
6177
+ components: [
5721
6178
  {
5722
- internalType: "uint128",
5723
- name: "liquidityGross",
5724
- type: "uint128"
6179
+ name: "tokenIn",
6180
+ type: "address"
5725
6181
  },
5726
6182
  {
5727
- internalType: "int128",
5728
- name: "liquidityNet",
5729
- type: "int128"
6183
+ name: "tokenOut",
6184
+ type: "address"
5730
6185
  },
5731
6186
  {
5732
- internalType: "uint256",
5733
- name: "feeGrowthOutside0X128",
6187
+ name: "amountIn",
5734
6188
  type: "uint256"
5735
6189
  },
5736
6190
  {
5737
- internalType: "uint256",
5738
- name: "feeGrowthOutside1X128",
5739
- type: "uint256"
6191
+ name: "fee",
6192
+ type: "uint24"
5740
6193
  },
5741
6194
  {
5742
- internalType: "int56",
5743
- name: "tickCumulativeOutside",
5744
- type: "int56"
6195
+ name: "sqrtPriceLimitX96",
6196
+ type: "uint160"
6197
+ }
6198
+ ]
6199
+ }],
6200
+ outputs: [
6201
+ {
6202
+ name: "amountOut",
6203
+ type: "uint256"
6204
+ },
6205
+ {
6206
+ name: "sqrtPriceX96After",
6207
+ type: "uint160"
6208
+ },
6209
+ {
6210
+ name: "initializedTicksCrossed",
6211
+ type: "uint32"
6212
+ },
6213
+ {
6214
+ name: "gasEstimate",
6215
+ type: "uint256"
6216
+ }
6217
+ ]
6218
+ }, {
6219
+ type: "function",
6220
+ name: "quoteExactOutputSingle",
6221
+ stateMutability: "nonpayable",
6222
+ inputs: [{
6223
+ name: "params",
6224
+ type: "tuple",
6225
+ components: [
6226
+ {
6227
+ name: "tokenIn",
6228
+ type: "address"
5745
6229
  },
5746
6230
  {
5747
- internalType: "uint160",
5748
- name: "secondsPerLiquidityOutsideX128",
5749
- type: "uint160"
6231
+ name: "tokenOut",
6232
+ type: "address"
5750
6233
  },
5751
6234
  {
5752
- internalType: "uint32",
5753
- name: "secondsOutside",
5754
- type: "uint32"
6235
+ name: "amount",
6236
+ type: "uint256"
5755
6237
  },
5756
6238
  {
5757
- internalType: "bool",
5758
- name: "initialized",
5759
- type: "bool"
6239
+ name: "fee",
6240
+ type: "uint24"
6241
+ },
6242
+ {
6243
+ name: "sqrtPriceLimitX96",
6244
+ type: "uint160"
5760
6245
  }
5761
- ],
5762
- stateMutability: "view",
5763
- type: "function"
5764
- },
5765
- {
5766
- inputs: [],
5767
- name: "liquidity",
5768
- outputs: [{
5769
- internalType: "uint128",
5770
- name: "",
5771
- type: "uint128"
5772
- }],
5773
- stateMutability: "view",
5774
- type: "function"
5775
- },
5776
- {
5777
- inputs: [],
5778
- name: "fee",
5779
- outputs: [{
5780
- internalType: "uint24",
5781
- name: "",
5782
- type: "uint24"
5783
- }],
5784
- stateMutability: "view",
5785
- type: "function"
5786
- },
5787
- {
5788
- inputs: [],
5789
- name: "token0",
5790
- outputs: [{
5791
- internalType: "address",
5792
- name: "",
5793
- type: "address"
5794
- }],
5795
- stateMutability: "view",
5796
- type: "function"
5797
- },
5798
- {
5799
- inputs: [],
5800
- name: "token1",
5801
- outputs: [{
5802
- internalType: "address",
5803
- name: "",
5804
- type: "address"
5805
- }],
5806
- stateMutability: "view",
5807
- type: "function"
5808
- },
5809
- {
5810
- inputs: [],
5811
- name: "tickSpacing",
5812
- outputs: [{
5813
- internalType: "int24",
5814
- name: "",
5815
- type: "int24"
5816
- }],
5817
- stateMutability: "view",
5818
- type: "function"
6246
+ ]
6247
+ }],
6248
+ outputs: [
6249
+ {
6250
+ name: "amountIn",
6251
+ type: "uint256"
6252
+ },
6253
+ {
6254
+ name: "sqrtPriceX96After",
6255
+ type: "uint160"
6256
+ },
6257
+ {
6258
+ name: "initializedTicksCrossed",
6259
+ type: "uint32"
6260
+ },
6261
+ {
6262
+ name: "gasEstimate",
6263
+ type: "uint256"
6264
+ }
6265
+ ]
6266
+ }];
6267
+
6268
+ //#endregion
6269
+ //#region src/uniswap/v3/router/quote.ts
6270
+ const BPS_DENOMINATOR$2 = 10000n;
6271
+ const UINT128_MAX$3 = (1n << 128n) - 1n;
6272
+ /**
6273
+ * Quote an exact-in v3 swap. Returns `null` when the quote reverts (e.g. the
6274
+ * pool does not exist / has no liquidity) so callers can skip that pool when
6275
+ * ranking venues, rather than aborting the whole cycle.
6276
+ */
6277
+ async function quoteV3ExactIn(params) {
6278
+ const { client, chainId, tokenIn, tokenOut, fee, amountIn, slippageBps, blockNumber } = params;
6279
+ if (amountIn < 0n || amountIn > UINT128_MAX$3) throw new PanopticError(`amountIn ${amountIn} exceeds uint128 maximum`);
6280
+ assertSlippageBps$1(slippageBps);
6281
+ const { quoterV2 } = getUniswapV3Addresses(chainId, params.addresses);
6282
+ try {
6283
+ const { result } = await client.simulateContract({
6284
+ address: quoterV2,
6285
+ abi: quoterV2Abi,
6286
+ functionName: "quoteExactInputSingle",
6287
+ blockNumber,
6288
+ args: [{
6289
+ tokenIn,
6290
+ tokenOut,
6291
+ amountIn,
6292
+ fee: Number(fee),
6293
+ sqrtPriceLimitX96: 0n
6294
+ }]
6295
+ });
6296
+ const [amountOut, , , gasEstimate] = result;
6297
+ const amountOutMinimum = amountOut * (BPS_DENOMINATOR$2 - slippageBps) / BPS_DENOMINATOR$2;
6298
+ return {
6299
+ amountOut,
6300
+ amountOutMinimum,
6301
+ gasEstimate
6302
+ };
6303
+ } catch (err) {
6304
+ if (isRevert$1(err)) return null;
6305
+ throw err;
5819
6306
  }
5820
- ];
6307
+ }
6308
+ /**
6309
+ * Quote an exact-out v3 swap. Returns `null` on revert (no pool / no liquidity).
6310
+ */
6311
+ async function quoteV3ExactOut(params) {
6312
+ const { client, chainId, tokenIn, tokenOut, fee, amountOut, slippageBps, blockNumber } = params;
6313
+ if (amountOut < 0n || amountOut > UINT128_MAX$3) throw new PanopticError(`amountOut ${amountOut} exceeds uint128 maximum`);
6314
+ assertSlippageBps$1(slippageBps);
6315
+ const { quoterV2 } = getUniswapV3Addresses(chainId, params.addresses);
6316
+ try {
6317
+ const { result } = await client.simulateContract({
6318
+ address: quoterV2,
6319
+ abi: quoterV2Abi,
6320
+ functionName: "quoteExactOutputSingle",
6321
+ blockNumber,
6322
+ args: [{
6323
+ tokenIn,
6324
+ tokenOut,
6325
+ amount: amountOut,
6326
+ fee: Number(fee),
6327
+ sqrtPriceLimitX96: 0n
6328
+ }]
6329
+ });
6330
+ const [amountIn, , , gasEstimate] = result;
6331
+ const amountInMaximum = (amountIn * (BPS_DENOMINATOR$2 + slippageBps) + BPS_DENOMINATOR$2 - 1n) / BPS_DENOMINATOR$2;
6332
+ return {
6333
+ amountIn,
6334
+ amountInMaximum,
6335
+ gasEstimate
6336
+ };
6337
+ } catch (err) {
6338
+ if (isRevert$1(err)) return null;
6339
+ throw err;
6340
+ }
6341
+ }
6342
+ function assertSlippageBps$1(slippageBps) {
6343
+ if (slippageBps < 0n || slippageBps > BPS_DENOMINATOR$2) throw new PanopticError(`invalid slippageBps ${slippageBps}, must be 0..10000`);
6344
+ }
6345
+ function isRevert$1(err) {
6346
+ return err instanceof BaseError && err.walk((e) => e instanceof ContractFunctionRevertedError) instanceof ContractFunctionRevertedError;
6347
+ }
5821
6348
 
5822
6349
  //#endregion
5823
6350
  //#region src/panoptic/v2/utils/oraclePack.ts
@@ -7792,5 +8319,5 @@ async function swapExactOutViaRouterAndWait(params) {
7792
8319
  }
7793
8320
 
7794
8321
  //#endregion
7795
- export { AmountExceedsUint128Error, InvalidSwapTokenError, LP_RANGE_HORIZONS_DAYS, LP_RANGE_HORIZONS_YEARS, MSG_SENDER, MissingSweepRecipientError, PERMIT2_ADDRESS, QuoterUnavailableError, SETTLE_ALL, SWAP_EXACT_IN_SINGLE, SWAP_EXACT_OUT_SINGLE, SWEEP, TAKE_ALL, UNISWAP_V3_ADDRESSES, UNISWAP_V4_ADDRESSES, UnsupportedChainError, V3_SWAP_EXACT_IN, V3_SWAP_EXACT_OUT, V4_SWAP, annualizeLpFeeReturn, approveErc20ForPermit2, approveErc20ForPermit2AndWait, approveRouterViaPermit2, approveRouterViaPermit2AndWait, buildV3ExactOutSwapExecuteArgs, buildV3ExactOutSwapExecuteCalldata, buildV3SwapExecuteArgs, buildV3SwapExecuteCalldata, buildV4ExactOutSwapExecuteArgs, buildV4ExactOutSwapExecuteCalldata, buildV4SwapExecuteArgs, buildV4SwapExecuteCalldata, calculateLpPositionVolatility, checkRouterApproval, encodeV3Path, estimateLpFees, expectedTimeInRange, getAmountsForLiquidity, getLpDepositAmounts, getLpDepositBreakdown, getLpFeeReturnSeries, getLpFundingDeposit, getLpGreeks, getLpPositionFunding, getMaxLpPositionSize, getUnhedgedLpRanges, getUniswapV3Addresses, getUniswapV3PoolBalances, getUniswapV4Addresses, normalCdf, pInRangeAt, quoteSwapExactInViaRouter, quoteSwapExactInViaV3Router, quoteSwapExactOutViaRouter, quoteSwapExactOutViaV3Router, quoteTokenPrices, quoteV3ExactIn, quoteV3ExactOut, quoteV4ExactInByPoolKey, rangeStats, resolveSwapRoute, resolveV3SwapRoute, swapExactInViaRouter, swapExactInViaRouterAndWait, swapExactInViaV3Router, swapExactOutViaRouter, swapExactOutViaRouterAndWait, swapExactOutViaV3Router };
8322
+ export { AmountExceedsUint128Error, InvalidSwapTokenError, LP_RANGE_HORIZONS_DAYS, LP_RANGE_HORIZONS_YEARS, MSG_SENDER, MissingSweepRecipientError, PERMIT2_ADDRESS, QuoterUnavailableError, SETTLE_ALL, SWAP_EXACT_IN_SINGLE, SWAP_EXACT_OUT_SINGLE, SWEEP, TAKE_ALL, UNISWAP_V3_ADDRESSES, UNISWAP_V4_ADDRESSES, UnsupportedChainError, V3_SWAP_EXACT_IN, V3_SWAP_EXACT_OUT, V4_SWAP, annualizeLpFeeReturn, approveErc20ForPermit2, approveErc20ForPermit2AndWait, approveRouterViaPermit2, approveRouterViaPermit2AndWait, buildV3ExactOutSwapExecuteArgs, buildV3ExactOutSwapExecuteCalldata, buildV3SwapExecuteArgs, buildV3SwapExecuteCalldata, buildV4ExactOutSwapExecuteArgs, buildV4ExactOutSwapExecuteCalldata, buildV4SwapExecuteArgs, buildV4SwapExecuteCalldata, calculateLpPositionVolatility, calculateV3LpAccounting, checkRouterApproval, encodeV3Path, estimateLpFees, expectedTimeInRange, getAmountsForLiquidity, getLpDepositAmounts, getLpDepositBreakdown, getLpFeeReturnSeries, getLpFundingDeposit, getLpGreeks, getLpPositionFunding, getLpPositionHistory, getMaxLpPositionSize, getUnhedgedLpRanges, getUniswapV3Addresses, getUniswapV3PoolBalances, getUniswapV4Addresses, getV3LpHistoryAccounting, normalCdf, pInRangeAt, quoteSwapExactInViaRouter, quoteSwapExactInViaV3Router, quoteSwapExactOutViaRouter, quoteSwapExactOutViaV3Router, quoteTokenPrices, quoteV3ExactIn, quoteV3ExactOut, quoteV4ExactInByPoolKey, rangeStats, resolveSwapRoute, resolveV3SwapRoute, summarizeLpPositionHistory, swapExactInViaRouter, swapExactInViaRouterAndWait, swapExactInViaV3Router, swapExactOutViaRouter, swapExactOutViaRouterAndWait, swapExactOutViaV3Router };
7796
8323
  //# sourceMappingURL=index.js.map