Skip to content

feat(swap-vm): add computeSingleSidedRange to ConcentrateLiquidityCalculator#79

Draft
krboktv wants to merge 2 commits into
masterfrom
cursor/single-sided-range-calculator
Draft

feat(swap-vm): add computeSingleSidedRange to ConcentrateLiquidityCalculator#79
krboktv wants to merge 2 commits into
masterfrom
cursor/single-sided-range-calculator

Conversation

@krboktv

@krboktv krboktv commented Jul 12, 2026

Copy link
Copy Markdown
Member

Summary

Adds ConcentrateLiquidityCalculator.computeSingleSidedRange(spotPrice, reserveForToken, reserve): builds a single-sided price range from the spot price and a single deposited reserve, and returns the resulting PriceAllocationRange.

The spot price sits exactly on one bound, depending on the deposited token (in sqrt(token1/token0) terms):

  • depositing token0: spot = min bound;
  • depositing token1: spot = max bound.

The opposite bound is derived from the other token's maxAvailableLiquidity: it is the price at which the deposited reserve fully converts into exactly that amount, via the range-order relation sqrtPmin * sqrtPmax = amountGt / amountLt (the geometric mean of the bounds is the average execution price across the range). The opposite token's maxAvailableLiquidity must therefore exceed the spot-equivalent value of the deposit, otherwise the method throws.

Example (USDC 6dp / WETH 18dp): deposit 1,000,000 USDC at spot 2500 USDC/WETH with maxAvailableLiquidity of 800 WETH → range [2500, 625] USDC per WETH; average execution sqrt(2500·625) = 1250, and the deposit converts into exactly 800 WETH at the far bound (verified bit-exact in tests).

Changes

  • concentrate-liquidity-calculator.ts: new computeSingleSidedRange method with validation (positive reserve, pair-matching spot price, reserve token in pair, opposite maxAvailableLiquidity large enough for a non-degenerate range).
  • index.ts: export the ConcentrateLiquidityCalculator class (previously only its types were exported, contrary to the module docs).
  • CONCENTRATE-LIQUIDITY-CALCULATOR.md: documentation for the new method.
  • New test file concentrate-liquidity-calculator.test.ts with 11 tests: both deposit directions (spot placement, derived bound value, exact full conversion into the target at the far bound via the liquidity math, compatibility with computeFixedAllocation) and all error paths.

Testing

  • pnpm test in typescript/swap-vm: 606 tests passed (45 files), including the 11 new ones.
  • pnpm type-check, pnpm lint, pnpm format:check: all clean.
Open in Web Open in Cursor 

cursoragent and others added 2 commits July 12, 2026 15:51
…culator

Build a single-sided range from a spot price, one price bound and a single
reserve: the spot itself becomes the second bound (min for a token0 deposit,
max for a token1 deposit) and the opposite reserve defaults to zero. Returns
the resulting PriceAllocationRange together with the reserves, ready for the
allocation methods and the SwapVM concentrate instructions.

Also export ConcentrateLiquidityCalculator from the concentrate instructions
index (previously only its types were exported, contrary to the docs).

Co-authored-by: Kirill <krboktv@gmail.com>
…stead of accepting it

Per review: the method now accepts only spotPrice, reserveForToken and
reserve, and returns the price range. The spot sits on the min bound for a
token0 deposit and on the max bound for a token1 deposit; the opposite bound
is derived from the other token's maxAvailableLiquidity via the range-order
relation sqrtPmin * sqrtPmax = amountGt / amountLt, i.e. the price at which
the deposit fully converts into exactly that amount. Drop the now-unneeded
SingleSidedRangeInfo type.

Co-authored-by: Kirill <krboktv@gmail.com>
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants