@sundaeswap/math 0.4.0 → 0.5.1

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.
@@ -3,10 +3,16 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.pinnedDepositFromAnchor = exports.getSwapOutput = exports.getSwapInput = exports.calculatePinnedDeposit = exports.calculateLiquidity = exports.calculateDepositN = void 0;
6
+ exports.pinnedDepositFromAnchor = exports.getSwapOutput = exports.getSwapInput = exports.calculateZap = exports.calculatePinnedDeposit = exports.calculateLiquidity = exports.calculateDepositN = void 0;
7
7
  var _asset = require("@sundaeswap/asset");
8
8
  var _fraction = require("@sundaeswap/fraction");
9
9
  var _index = require("./index.js");
10
+ function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
11
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
12
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
13
+ function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
14
+ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
15
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
10
16
  /**
11
17
  * Holds the calculated outcome of a constant-sum swap. Mirrors
12
18
  * {@link ConstantProductPool.TSwapOutcome} so both can flow through the same
@@ -281,4 +287,103 @@ var calculateDepositN = exports.calculateDepositN = function calculateDepositN(a
281
287
  shareAfterDeposit: _index.SharedPoolMath.getShare(generatedLp, nextTotalLp)
282
288
  };
283
289
  };
290
+
291
+ /**
292
+ * Outcome of {@link calculateZap}. Every array is aligned to `offered`.
293
+ */
294
+
295
+ /**
296
+ * A zap on a 2-asset constant-sum pool: a non-proportional `offered` basket
297
+ * is rebalanced by swapping part of the over-weighted asset, then deposited
298
+ * under the target-pinned rule ({@link calculatePinnedDeposit}). The swap
299
+ * amount `dx` is the one that leaves the post-swap basket proportional to
300
+ * the post-swap reserves, so the pin consumes the whole basket up to
301
+ * rounding. With `k = (1−fee)·p_X/p_Y`,
302
+ *
303
+ * (a_X − dx)/(r_X + dx) = (a_Y + k·dx)/(r_Y − k·dx)
304
+ * ⇒ dx = (a_X·r_Y − a_Y·r_X) / (k·(r_X + a_X) + (r_Y + a_Y))
305
+ *
306
+ * (the dx² terms cancel). `dx` is floored and the swap leg follows
307
+ * {@link getSwapOutput}; whatever imbalance rounding leaves comes back as
308
+ * `change`.
309
+ *
310
+ * `fee` is the pool's fee for the swap direction — v4 splits bid and ask, so
311
+ * the caller picks. Two assets only: with more, which assets to swap is an
312
+ * allocation problem this formula does not address.
313
+ */
314
+ var calculateZap = exports.calculateZap = function calculateZap(offered, reserves, prices, totalLp, fee) {
315
+ if (offered.length !== 2 || reserves.length !== 2 || prices.length !== 2) throw new Error("calculateZap supports exactly two assets");
316
+ if (prices.some(function (p) {
317
+ return p <= 0n;
318
+ })) throw new Error("Prices must be positive");
319
+ if (reserves.some(function (r) {
320
+ return r <= 0n;
321
+ })) throw new Error("Reserves must be positive");
322
+ if (offered.some(function (a) {
323
+ return a < 0n;
324
+ }) || offered.every(function (a) {
325
+ return a === 0n;
326
+ })) throw new Error("Offered amounts must be non-negative, with at least one positive");
327
+ if (totalLp <= 0n) throw new Error("Not enough pool liquidity");
328
+ var feeFraction = _fraction.Fraction.asFraction(fee);
329
+ if (feeFraction.lt(_fraction.Fraction.ZERO) || feeFraction.gte(_fraction.Fraction.ONE)) throw new Error("fee must be [0,1)");
330
+ var feeNum = BigInt(feeFraction.numerator);
331
+ var feeDen = BigInt(feeFraction.denominator);
332
+
333
+ // Over-weighted side: compare a_0/r_0 against a_1/r_1 without division.
334
+ var lhs = offered[0] * reserves[1];
335
+ var rhs = offered[1] * reserves[0];
336
+ var swapIndex = lhs > rhs ? 0 : lhs < rhs ? 1 : undefined;
337
+ var swapInput = 0n;
338
+ var swapOutput = 0n;
339
+ var nextReserves = _toConsumableArray(reserves);
340
+ var depositBasket = _toConsumableArray(offered);
341
+ if (swapIndex !== undefined) {
342
+ var x = swapIndex;
343
+ var y = 1 - swapIndex;
344
+ var _ref = [offered[x], offered[y]],
345
+ aX = _ref[0],
346
+ aY = _ref[1];
347
+ var _ref2 = [reserves[x], reserves[y]],
348
+ rX = _ref2[0],
349
+ rY = _ref2[1];
350
+ var _ref3 = [prices[x], prices[y]],
351
+ pX = _ref3[0],
352
+ pY = _ref3[1];
353
+
354
+ // dx with k = (feeDen−feeNum)·pX / (feeDen·pY), cleared of denominators.
355
+ var numerator = (aX * rY - aY * rX) * feeDen * pY;
356
+ var denominator = (feeDen - feeNum) * pX * (rX + aX) + feeDen * pY * (rY + aY);
357
+ swapInput = numerator / denominator;
358
+ if (swapInput > 0n) {
359
+ var inputValue = swapInput * pX;
360
+ var feeValue = inputValue * feeNum / feeDen;
361
+ swapOutput = (inputValue - feeValue) / pY;
362
+ if (swapOutput >= rY) throw new Error("Pool too shallow: the rebalancing swap would drain it");
363
+ nextReserves[x] = rX + swapInput;
364
+ nextReserves[y] = rY - swapOutput;
365
+ depositBasket[x] = aX - swapInput;
366
+ depositBasket[y] = aY + swapOutput;
367
+ }
368
+ }
369
+ if (depositBasket.some(function (a) {
370
+ return a <= 0n;
371
+ })) throw new Error("Offered amount too small to zap into this pool");
372
+ var pinned = calculatePinnedDeposit(depositBasket, nextReserves, prices, totalLp);
373
+ return {
374
+ swapIndex: swapIndex,
375
+ swapInput: swapInput,
376
+ swapOutput: swapOutput,
377
+ nextReserves: nextReserves,
378
+ depositBasket: depositBasket,
379
+ deltas: pinned.deltas,
380
+ change: depositBasket.map(function (a, i) {
381
+ return a - pinned.deltas[i];
382
+ }),
383
+ targetDeltaV: pinned.targetDeltaV,
384
+ generatedLp: pinned.generatedLp,
385
+ nextTotalLp: pinned.nextTotalLp,
386
+ shareAfterDeposit: pinned.shareAfterDeposit
387
+ };
388
+ };
284
389
  //# sourceMappingURL=ConstantSumPool.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ConstantSumPool.js","names":["_asset","require","_fraction","_index","getSwapOutput","exports","inputMetadata","input","inputReserve","outputReserve","priceIn","priceOut","fee","roundOutputUp","Error","feeFraction","Fraction","asFraction","lt","ZERO","gt","ONE","inputValue","feeValue","BigInt","numerator","denominator","quotient","outputValue","output","inputLpFee","nextInputReserve","nextOutputReserve","priceImpact","amountInLessFee","idealPrice","actualPrice","subtract","divide","lpFee","AssetAmount","getSwapInput","gte","feeNum","feeDen","feeDiff","targetValue","calculateLiquidity","a","b","aReserve","bReserve","totalLp","priceA","priceB","_calculatePinnedDepos","calculatePinnedDeposit","deltas","generatedLp","nextTotalLp","shareAfterDeposit","aChange","bChange","actualDepositedA","actualDepositedB","offered","reserves","prices","length","some","p","vB","i","t","cap","undefined","map","r","targetDeltaV","SharedPoolMath","getShare","pinnedDepositFromAnchor","anchorIndex","anchorAmount","calculateDepositN","amounts","every","totalValue","depositValue"],"sources":["../../../src/PoolMath/ConstantSumPool.ts"],"sourcesContent":["import { AssetAmount, IAssetAmountMetadata } from \"@sundaeswap/asset\";\nimport { Fraction, type TFractionLike } from \"@sundaeswap/fraction\";\nimport { SharedPoolMath } from \"./index.js\";\n\n/**\n * Holds the calculated outcome of a constant-sum swap. Mirrors\n * {@link ConstantProductPool.TSwapOutcome} so both can flow through the same\n * generic swap-outcome consumers.\n */\nexport type TSwapOutcome = {\n input: bigint;\n output: bigint;\n lpFee: AssetAmount<IAssetAmountMetadata>;\n nextInputReserve: bigint;\n nextOutputReserve: bigint;\n priceImpact: Fraction;\n};\n\n/**\n * Calculate the swap outcome for a constant-sum (fixed-price) pool — the\n * invariant used by Sundae v4 stable/pegged pools. Unlike constant product,\n * the exchange rate is fixed by the pool's per-asset `prices`: the input is\n * converted to \"value\" at `priceIn`, the fee is taken off that value, and the\n * remainder is converted to the output asset at `priceOut`. The result is\n * capped at the output reserve (you can't take more than the pool holds).\n *\n * Matches the scooper's `cs_swap_result`:\n * output = floor((input·priceIn − floor(input·priceIn·fee)) / priceOut)\n *\n * @param inputMetadata Metadata for the supplied (input) asset — used for the fee AssetAmount.\n * @param input The amount of the input asset being swapped.\n * @param inputReserve The pool's reserve of the input asset.\n * @param outputReserve The pool's reserve of the output asset.\n * @param priceIn The pool's price for the input asset (from the constant-sum config).\n * @param priceOut The pool's price for the output asset.\n * @param fee The liquidity-provider fee (plus protocol fee) as a fraction.\n * @param roundOutputUp When true, round the output up instead of flooring.\n * @returns The swap details in the shared {@link TSwapOutcome} shape.\n */\nexport const getSwapOutput = (\n inputMetadata: IAssetAmountMetadata,\n input: bigint,\n inputReserve: bigint,\n outputReserve: bigint,\n priceIn: bigint,\n priceOut: bigint,\n fee: TFractionLike,\n roundOutputUp?: boolean,\n): TSwapOutcome => {\n if (input <= 0n || inputReserve <= 0n || outputReserve <= 0n)\n throw new Error(\"Input and reserves must be positive\");\n if (priceIn <= 0n || priceOut <= 0n)\n throw new Error(\"Prices must be positive\");\n\n const feeFraction = Fraction.asFraction(fee);\n if (feeFraction.lt(Fraction.ZERO) || feeFraction.gt(Fraction.ONE))\n throw new Error(\"fee must be between 0 and 1\");\n\n const inputValue = input * priceIn;\n const feeValue = new Fraction(\n inputValue * BigInt(feeFraction.numerator),\n BigInt(feeFraction.denominator),\n ).quotient;\n const outputValue = inputValue - feeValue;\n\n let output = roundOutputUp\n ? (outputValue + priceOut - 1n) / priceOut\n : outputValue / priceOut;\n\n // Can't take more than the pool holds.\n if (output > outputReserve) {\n output = outputReserve;\n }\n\n // LP fee expressed in input-asset units (value scales linearly with input,\n // so the input-denominated fee is input·feeRate) — matching ConstantProductPool.\n const inputLpFee = new Fraction(\n input * BigInt(feeFraction.numerator),\n BigInt(feeFraction.denominator),\n ).quotient;\n\n const nextInputReserve = inputReserve + input;\n const nextOutputReserve = outputReserve - output;\n\n // Price impact vs the pool's par price (priceOut/priceIn input-per-output);\n // ~0 for a constant-sum pool aside from the fee. See ConstantProductPool.\n let priceImpact = Fraction.ZERO;\n if (output > 0n) {\n const amountInLessFee = input - inputLpFee;\n const idealPrice = new Fraction(priceOut, priceIn);\n const actualPrice = new Fraction(amountInLessFee, output);\n priceImpact = Fraction.ONE.subtract(idealPrice.divide(actualPrice));\n }\n\n return {\n input,\n output,\n lpFee: new AssetAmount(inputLpFee, inputMetadata),\n nextInputReserve,\n nextOutputReserve,\n priceImpact,\n };\n};\n\n/**\n * Calculate the minimal input required to receive a given output from a\n * constant-sum pool — the exact inverse of {@link getSwapOutput}.\n *\n * The forward math floors the fee off the input value, which makes the\n * post-fee value `ceil(input·priceIn·(1−fee))`; inverting that ceiling gives\n * the smallest input whose forward swap yields at least `output`.\n *\n * Unlike constant product there is no asymptote, so an output equal to the\n * full output reserve is attainable (the pool can be drained at par).\n *\n * @param inputMetadata Metadata for the supplied (input) asset — used for the fee AssetAmount.\n * @param output The desired amount of the output asset.\n * @param inputReserve The pool's reserve of the input asset.\n * @param outputReserve The pool's reserve of the output asset.\n * @param priceIn The pool's price for the input asset (from the constant-sum config).\n * @param priceOut The pool's price for the output asset.\n * @param fee The liquidity-provider fee (plus protocol fee) as a fraction.\n * @returns The swap details in the shared {@link TSwapOutcome} shape.\n */\nexport const getSwapInput = (\n inputMetadata: IAssetAmountMetadata,\n output: bigint,\n inputReserve: bigint,\n outputReserve: bigint,\n priceIn: bigint,\n priceOut: bigint,\n fee: TFractionLike,\n): TSwapOutcome => {\n if (output <= 0n || inputReserve <= 0n || outputReserve <= 0n)\n throw new Error(\"Output and reserves must be positive\");\n if (priceIn <= 0n || priceOut <= 0n)\n throw new Error(\"Prices must be positive\");\n if (output > outputReserve)\n throw new Error(\"Output must not exceed the output reserve\");\n\n const feeFraction = Fraction.asFraction(fee);\n if (feeFraction.lt(Fraction.ZERO) || feeFraction.gte(Fraction.ONE))\n throw new Error(\"fee must be [0,1)\");\n\n const feeNum = BigInt(feeFraction.numerator);\n const feeDen = BigInt(feeFraction.denominator);\n const feeDiff = feeDen - feeNum;\n\n // Forward: outputValue = ceil(input·priceIn·feeDiff/feeDen), and the swap\n // yields ≥ output iff outputValue ≥ output·priceOut. ceil(x/d) ≥ T for\n // integer x iff x ≥ d·(T−1)+1, so the minimal input is the ceiling of\n // (feeDen·(output·priceOut − 1) + 1) / (feeDiff·priceIn).\n const targetValue = output * priceOut;\n const numerator = feeDen * (targetValue - 1n) + 1n;\n const denominator = feeDiff * priceIn;\n const input = (numerator + denominator - 1n) / denominator;\n\n const inputLpFee = new Fraction(input * feeNum, feeDen).quotient;\n const nextInputReserve = inputReserve + input;\n const nextOutputReserve = outputReserve - output;\n\n // Same par-price impact definition as getSwapOutput.\n const amountInLessFee = input - inputLpFee;\n const idealPrice = new Fraction(priceOut, priceIn);\n const actualPrice = new Fraction(amountInLessFee, output);\n const priceImpact = Fraction.ONE.subtract(idealPrice.divide(actualPrice));\n\n return {\n input,\n output,\n lpFee: new AssetAmount(inputLpFee, inputMetadata),\n nextInputReserve,\n nextOutputReserve,\n priceImpact,\n };\n};\n\n/**\n * Calculate the deposit parameters for a 2-asset constant-sum pool via the\n * TARGET-PINNED rule the deployed validator enforces (see\n * {@link calculatePinnedDeposit}): the mint is capped by the scarcest offered\n * asset, both assets must be offered, and anything above the pinned deltas is\n * refunded via aChange/bChange.\n *\n * @param {bigint} a - The amount of token A to deposit.\n * @param {bigint} b - The amount of token B to deposit.\n * @param {bigint} aReserve - The current reserve of token A in the pool.\n * @param {bigint} bReserve - The current reserve of token B in the pool.\n * @param {bigint} totalLp - The total lp tokens for the pool before the deposit.\n * @param {bigint} priceA - The pool's price for token A (from the constant-sum config).\n * @param {bigint} priceB - The pool's price for token B.\n * @throws {Error} If the pool has no value or minted lp.\n * @throws {Error} If both deposit amounts are zero, or either is negative.\n * @throws {Error} If either price is non-positive.\n */\nexport const calculateLiquidity = (\n a: bigint,\n b: bigint,\n aReserve: bigint,\n bReserve: bigint,\n totalLp: bigint,\n priceA: bigint,\n priceB: bigint,\n) => {\n // Target-pinned (what the deployed validator accepts): mint by the\n // scarcest offered asset; anything above the pinned deltas is refunded\n // (aChange/bChange).\n const { deltas, generatedLp, nextTotalLp, shareAfterDeposit } =\n calculatePinnedDeposit(\n [a, b],\n [aReserve, bReserve],\n [priceA, priceB],\n totalLp,\n );\n\n return {\n nextTotalLp,\n generatedLp,\n shareAfterDeposit,\n aChange: a - deltas[0],\n bChange: b - deltas[1],\n actualDepositedA: deltas[0],\n actualDepositedB: deltas[1],\n };\n};\n\n/**\n * The N-asset form of {@link calculateLiquidity}, mirroring the v4 contract's\n * `compute_deposit_n` exactly: a deposit of any mix of the pool's assets is\n * valued at the fixed prices against the value of ALL reserves —\n *\n * generatedLp = Σ(amount_i·price_i) · totalLp / Σ(reserve_i·price_i)\n *\n * The three arrays must be aligned to the pool's canonical asset order (the\n * API's `assets`/`quantities`/`prices`). Estimating an N-asset pool's deposit\n * from just two of its reserves overstates the minted LP — the denominator is\n * the whole pool's value — which is exactly the mistake this exists to\n * prevent.\n */\n/**\n * The target-pinned deposit — what the deployed CS validator (cs_check tag 6)\n * actually accepts, and what the scooper builds. Asymmetric deposits are\n * disallowed on-chain: the fill declares a value delta `t` and every asset's\n * contribution is ceil-pinned to `ceil(r_i·t/V_b)`, with total LP\n * floor-pinned to `floor(lp_b·(V_b+t)/V_b)`. Given what the user offers, the\n * largest fillable t is capped by the SCARCEST asset —\n * `t = min_i floor(offered_i·V_b/r_i)` — and anything above the pinned\n * deltas is returned as surplus. Every pool asset must be offered (> 0) or\n * t is zero and the deposit can never fill.\n *\n * Contrast with `calculateDepositN`, which is the plain value formula:\n * it matches the pin only for exactly proportional offers and OVERSTATES the\n * mint otherwise — using it for `minReceived` makes non-proportional orders\n * unfillable.\n */\nexport const calculatePinnedDeposit = (\n offered: bigint[],\n reserves: bigint[],\n prices: bigint[],\n totalLp: bigint,\n): {\n targetDeltaV: bigint;\n deltas: bigint[];\n generatedLp: bigint;\n nextTotalLp: bigint;\n shareAfterDeposit: Fraction;\n} => {\n if (offered.length !== reserves.length || reserves.length !== prices.length)\n throw new Error(\"offered, reserves and prices must be aligned\");\n if (prices.some((p) => p <= 0n)) throw new Error(\"Prices must be positive\");\n if (totalLp <= 0n) throw new Error(\"Not enough pool liquidity\");\n\n let vB = 0n;\n for (let i = 0; i < reserves.length; i++) {\n vB += reserves[i] * prices[i];\n }\n if (vB <= 0n) throw new Error(\"Pool value is zero\");\n\n let t: bigint | undefined;\n for (let i = 0; i < offered.length; i++) {\n if (reserves[i] === 0n) continue;\n const cap = (offered[i] * vB) / reserves[i];\n t = t === undefined || cap < t ? cap : t;\n }\n if (t === undefined || t <= 0n) {\n throw new Error(\n \"A constant-sum deposit must offer every pool asset in proportion (asymmetric deposits are disallowed on-chain)\",\n );\n }\n\n const deltas = reserves.map((r) => (r * t! + vB - 1n) / vB); // ceil\n const nextTotalLp = (totalLp * (vB + t)) / vB; // floor\n const generatedLp = nextTotalLp - totalLp;\n if (generatedLp <= 0n) throw new Error(\"Deposit mints zero LP\");\n\n return {\n targetDeltaV: t,\n deltas,\n generatedLp,\n nextTotalLp,\n shareAfterDeposit: SharedPoolMath.getShare(generatedLp, nextTotalLp),\n };\n};\n\n/**\n * The per-asset amounts a pinned deposit needs when the user anchors on one\n * asset's amount: t from the anchor (`floor(anchor·V_b/r_anchor)`), every\n * delta ceil-pinned to it. Drives proportional auto-fill in deposit forms.\n */\nexport const pinnedDepositFromAnchor = (\n anchorIndex: number,\n anchorAmount: bigint,\n reserves: bigint[],\n prices: bigint[],\n): bigint[] => {\n if (reserves.length !== prices.length)\n throw new Error(\"reserves and prices must be aligned\");\n if (\n anchorIndex < 0 ||\n anchorIndex >= reserves.length ||\n reserves[anchorIndex] <= 0n\n )\n throw new Error(\"anchor asset has no reserve\");\n if (anchorAmount <= 0n) return reserves.map(() => 0n);\n\n let vB = 0n;\n for (let i = 0; i < reserves.length; i++) {\n vB += reserves[i] * prices[i];\n }\n if (vB <= 0n) throw new Error(\"Pool value is zero\");\n\n const t = (anchorAmount * vB) / reserves[anchorIndex];\n return reserves.map((r, i) =>\n i === anchorIndex ? anchorAmount : (r * t + vB - 1n) / vB,\n );\n};\n\nexport const calculateDepositN = (\n amounts: bigint[],\n reserves: bigint[],\n prices: bigint[],\n totalLp: bigint,\n) => {\n if (amounts.length !== reserves.length || reserves.length !== prices.length)\n throw new Error(\"amounts, reserves and prices must be aligned\");\n if (prices.some((p) => p <= 0n)) throw new Error(\"Prices must be positive\");\n // Zeros in a MIX are fine — offering a subset is the point of the N-asset\n // form. What's rejected is a negative amount, or offering nothing at all.\n if (amounts.some((a) => a < 0n) || amounts.every((a) => a === 0n))\n throw new Error(\n \"Deposit amounts must be non-negative, with at least one positive\",\n );\n\n let totalValue = 0n;\n let depositValue = 0n;\n for (let i = 0; i < amounts.length; i++) {\n totalValue += reserves[i] * prices[i];\n depositValue += amounts[i] * prices[i];\n }\n if (totalValue <= 0n || totalLp <= 0n)\n throw new Error(\"Not enough pool liquidity\");\n\n const generatedLp = (depositValue * totalLp) / totalValue;\n const nextTotalLp = totalLp + generatedLp;\n\n return {\n nextTotalLp,\n generatedLp,\n shareAfterDeposit: SharedPoolMath.getShare(generatedLp, nextTotalLp),\n };\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"ConstantSumPool.js","names":["_asset","require","_fraction","_index","_toConsumableArray","r","_arrayWithoutHoles","_iterableToArray","_unsupportedIterableToArray","_nonIterableSpread","TypeError","a","_arrayLikeToArray","t","toString","call","slice","constructor","name","Array","from","test","Symbol","iterator","isArray","length","e","n","getSwapOutput","exports","inputMetadata","input","inputReserve","outputReserve","priceIn","priceOut","fee","roundOutputUp","Error","feeFraction","Fraction","asFraction","lt","ZERO","gt","ONE","inputValue","feeValue","BigInt","numerator","denominator","quotient","outputValue","output","inputLpFee","nextInputReserve","nextOutputReserve","priceImpact","amountInLessFee","idealPrice","actualPrice","subtract","divide","lpFee","AssetAmount","getSwapInput","gte","feeNum","feeDen","feeDiff","targetValue","calculateLiquidity","b","aReserve","bReserve","totalLp","priceA","priceB","_calculatePinnedDepos","calculatePinnedDeposit","deltas","generatedLp","nextTotalLp","shareAfterDeposit","aChange","bChange","actualDepositedA","actualDepositedB","offered","reserves","prices","some","p","vB","i","cap","undefined","map","targetDeltaV","SharedPoolMath","getShare","pinnedDepositFromAnchor","anchorIndex","anchorAmount","calculateDepositN","amounts","every","totalValue","depositValue","calculateZap","lhs","rhs","swapIndex","swapInput","swapOutput","nextReserves","depositBasket","x","y","_ref","aX","aY","_ref2","rX","rY","_ref3","pX","pY","pinned","change"],"sources":["../../../src/PoolMath/ConstantSumPool.ts"],"sourcesContent":["import { AssetAmount, IAssetAmountMetadata } from \"@sundaeswap/asset\";\nimport { Fraction, type TFractionLike } from \"@sundaeswap/fraction\";\nimport { SharedPoolMath } from \"./index.js\";\n\n/**\n * Holds the calculated outcome of a constant-sum swap. Mirrors\n * {@link ConstantProductPool.TSwapOutcome} so both can flow through the same\n * generic swap-outcome consumers.\n */\nexport type TSwapOutcome = {\n input: bigint;\n output: bigint;\n lpFee: AssetAmount<IAssetAmountMetadata>;\n nextInputReserve: bigint;\n nextOutputReserve: bigint;\n priceImpact: Fraction;\n};\n\n/**\n * Calculate the swap outcome for a constant-sum (fixed-price) pool — the\n * invariant used by Sundae v4 stable/pegged pools. Unlike constant product,\n * the exchange rate is fixed by the pool's per-asset `prices`: the input is\n * converted to \"value\" at `priceIn`, the fee is taken off that value, and the\n * remainder is converted to the output asset at `priceOut`. The result is\n * capped at the output reserve (you can't take more than the pool holds).\n *\n * Matches the scooper's `cs_swap_result`:\n * output = floor((input·priceIn − floor(input·priceIn·fee)) / priceOut)\n *\n * @param inputMetadata Metadata for the supplied (input) asset — used for the fee AssetAmount.\n * @param input The amount of the input asset being swapped.\n * @param inputReserve The pool's reserve of the input asset.\n * @param outputReserve The pool's reserve of the output asset.\n * @param priceIn The pool's price for the input asset (from the constant-sum config).\n * @param priceOut The pool's price for the output asset.\n * @param fee The liquidity-provider fee (plus protocol fee) as a fraction.\n * @param roundOutputUp When true, round the output up instead of flooring.\n * @returns The swap details in the shared {@link TSwapOutcome} shape.\n */\nexport const getSwapOutput = (\n inputMetadata: IAssetAmountMetadata,\n input: bigint,\n inputReserve: bigint,\n outputReserve: bigint,\n priceIn: bigint,\n priceOut: bigint,\n fee: TFractionLike,\n roundOutputUp?: boolean,\n): TSwapOutcome => {\n if (input <= 0n || inputReserve <= 0n || outputReserve <= 0n)\n throw new Error(\"Input and reserves must be positive\");\n if (priceIn <= 0n || priceOut <= 0n)\n throw new Error(\"Prices must be positive\");\n\n const feeFraction = Fraction.asFraction(fee);\n if (feeFraction.lt(Fraction.ZERO) || feeFraction.gt(Fraction.ONE))\n throw new Error(\"fee must be between 0 and 1\");\n\n const inputValue = input * priceIn;\n const feeValue = new Fraction(\n inputValue * BigInt(feeFraction.numerator),\n BigInt(feeFraction.denominator),\n ).quotient;\n const outputValue = inputValue - feeValue;\n\n let output = roundOutputUp\n ? (outputValue + priceOut - 1n) / priceOut\n : outputValue / priceOut;\n\n // Can't take more than the pool holds.\n if (output > outputReserve) {\n output = outputReserve;\n }\n\n // LP fee expressed in input-asset units (value scales linearly with input,\n // so the input-denominated fee is input·feeRate) — matching ConstantProductPool.\n const inputLpFee = new Fraction(\n input * BigInt(feeFraction.numerator),\n BigInt(feeFraction.denominator),\n ).quotient;\n\n const nextInputReserve = inputReserve + input;\n const nextOutputReserve = outputReserve - output;\n\n // Price impact vs the pool's par price (priceOut/priceIn input-per-output);\n // ~0 for a constant-sum pool aside from the fee. See ConstantProductPool.\n let priceImpact = Fraction.ZERO;\n if (output > 0n) {\n const amountInLessFee = input - inputLpFee;\n const idealPrice = new Fraction(priceOut, priceIn);\n const actualPrice = new Fraction(amountInLessFee, output);\n priceImpact = Fraction.ONE.subtract(idealPrice.divide(actualPrice));\n }\n\n return {\n input,\n output,\n lpFee: new AssetAmount(inputLpFee, inputMetadata),\n nextInputReserve,\n nextOutputReserve,\n priceImpact,\n };\n};\n\n/**\n * Calculate the minimal input required to receive a given output from a\n * constant-sum pool — the exact inverse of {@link getSwapOutput}.\n *\n * The forward math floors the fee off the input value, which makes the\n * post-fee value `ceil(input·priceIn·(1−fee))`; inverting that ceiling gives\n * the smallest input whose forward swap yields at least `output`.\n *\n * Unlike constant product there is no asymptote, so an output equal to the\n * full output reserve is attainable (the pool can be drained at par).\n *\n * @param inputMetadata Metadata for the supplied (input) asset — used for the fee AssetAmount.\n * @param output The desired amount of the output asset.\n * @param inputReserve The pool's reserve of the input asset.\n * @param outputReserve The pool's reserve of the output asset.\n * @param priceIn The pool's price for the input asset (from the constant-sum config).\n * @param priceOut The pool's price for the output asset.\n * @param fee The liquidity-provider fee (plus protocol fee) as a fraction.\n * @returns The swap details in the shared {@link TSwapOutcome} shape.\n */\nexport const getSwapInput = (\n inputMetadata: IAssetAmountMetadata,\n output: bigint,\n inputReserve: bigint,\n outputReserve: bigint,\n priceIn: bigint,\n priceOut: bigint,\n fee: TFractionLike,\n): TSwapOutcome => {\n if (output <= 0n || inputReserve <= 0n || outputReserve <= 0n)\n throw new Error(\"Output and reserves must be positive\");\n if (priceIn <= 0n || priceOut <= 0n)\n throw new Error(\"Prices must be positive\");\n if (output > outputReserve)\n throw new Error(\"Output must not exceed the output reserve\");\n\n const feeFraction = Fraction.asFraction(fee);\n if (feeFraction.lt(Fraction.ZERO) || feeFraction.gte(Fraction.ONE))\n throw new Error(\"fee must be [0,1)\");\n\n const feeNum = BigInt(feeFraction.numerator);\n const feeDen = BigInt(feeFraction.denominator);\n const feeDiff = feeDen - feeNum;\n\n // Forward: outputValue = ceil(input·priceIn·feeDiff/feeDen), and the swap\n // yields ≥ output iff outputValue ≥ output·priceOut. ceil(x/d) ≥ T for\n // integer x iff x ≥ d·(T−1)+1, so the minimal input is the ceiling of\n // (feeDen·(output·priceOut − 1) + 1) / (feeDiff·priceIn).\n const targetValue = output * priceOut;\n const numerator = feeDen * (targetValue - 1n) + 1n;\n const denominator = feeDiff * priceIn;\n const input = (numerator + denominator - 1n) / denominator;\n\n const inputLpFee = new Fraction(input * feeNum, feeDen).quotient;\n const nextInputReserve = inputReserve + input;\n const nextOutputReserve = outputReserve - output;\n\n // Same par-price impact definition as getSwapOutput.\n const amountInLessFee = input - inputLpFee;\n const idealPrice = new Fraction(priceOut, priceIn);\n const actualPrice = new Fraction(amountInLessFee, output);\n const priceImpact = Fraction.ONE.subtract(idealPrice.divide(actualPrice));\n\n return {\n input,\n output,\n lpFee: new AssetAmount(inputLpFee, inputMetadata),\n nextInputReserve,\n nextOutputReserve,\n priceImpact,\n };\n};\n\n/**\n * Calculate the deposit parameters for a 2-asset constant-sum pool via the\n * TARGET-PINNED rule the deployed validator enforces (see\n * {@link calculatePinnedDeposit}): the mint is capped by the scarcest offered\n * asset, both assets must be offered, and anything above the pinned deltas is\n * refunded via aChange/bChange.\n *\n * @param {bigint} a - The amount of token A to deposit.\n * @param {bigint} b - The amount of token B to deposit.\n * @param {bigint} aReserve - The current reserve of token A in the pool.\n * @param {bigint} bReserve - The current reserve of token B in the pool.\n * @param {bigint} totalLp - The total lp tokens for the pool before the deposit.\n * @param {bigint} priceA - The pool's price for token A (from the constant-sum config).\n * @param {bigint} priceB - The pool's price for token B.\n * @throws {Error} If the pool has no value or minted lp.\n * @throws {Error} If both deposit amounts are zero, or either is negative.\n * @throws {Error} If either price is non-positive.\n */\nexport const calculateLiquidity = (\n a: bigint,\n b: bigint,\n aReserve: bigint,\n bReserve: bigint,\n totalLp: bigint,\n priceA: bigint,\n priceB: bigint,\n) => {\n // Target-pinned (what the deployed validator accepts): mint by the\n // scarcest offered asset; anything above the pinned deltas is refunded\n // (aChange/bChange).\n const { deltas, generatedLp, nextTotalLp, shareAfterDeposit } =\n calculatePinnedDeposit(\n [a, b],\n [aReserve, bReserve],\n [priceA, priceB],\n totalLp,\n );\n\n return {\n nextTotalLp,\n generatedLp,\n shareAfterDeposit,\n aChange: a - deltas[0],\n bChange: b - deltas[1],\n actualDepositedA: deltas[0],\n actualDepositedB: deltas[1],\n };\n};\n\n/**\n * The N-asset form of {@link calculateLiquidity}, mirroring the v4 contract's\n * `compute_deposit_n` exactly: a deposit of any mix of the pool's assets is\n * valued at the fixed prices against the value of ALL reserves —\n *\n * generatedLp = Σ(amount_i·price_i) · totalLp / Σ(reserve_i·price_i)\n *\n * The three arrays must be aligned to the pool's canonical asset order (the\n * API's `assets`/`quantities`/`prices`). Estimating an N-asset pool's deposit\n * from just two of its reserves overstates the minted LP — the denominator is\n * the whole pool's value — which is exactly the mistake this exists to\n * prevent.\n */\n/**\n * The target-pinned deposit — what the deployed CS validator (cs_check tag 6)\n * actually accepts, and what the scooper builds. Asymmetric deposits are\n * disallowed on-chain: the fill declares a value delta `t` and every asset's\n * contribution is ceil-pinned to `ceil(r_i·t/V_b)`, with total LP\n * floor-pinned to `floor(lp_b·(V_b+t)/V_b)`. Given what the user offers, the\n * largest fillable t is capped by the SCARCEST asset —\n * `t = min_i floor(offered_i·V_b/r_i)` — and anything above the pinned\n * deltas is returned as surplus. Every pool asset must be offered (> 0) or\n * t is zero and the deposit can never fill.\n *\n * Contrast with `calculateDepositN`, which is the plain value formula:\n * it matches the pin only for exactly proportional offers and OVERSTATES the\n * mint otherwise — using it for `minReceived` makes non-proportional orders\n * unfillable.\n */\nexport const calculatePinnedDeposit = (\n offered: bigint[],\n reserves: bigint[],\n prices: bigint[],\n totalLp: bigint,\n): {\n targetDeltaV: bigint;\n deltas: bigint[];\n generatedLp: bigint;\n nextTotalLp: bigint;\n shareAfterDeposit: Fraction;\n} => {\n if (offered.length !== reserves.length || reserves.length !== prices.length)\n throw new Error(\"offered, reserves and prices must be aligned\");\n if (prices.some((p) => p <= 0n)) throw new Error(\"Prices must be positive\");\n if (totalLp <= 0n) throw new Error(\"Not enough pool liquidity\");\n\n let vB = 0n;\n for (let i = 0; i < reserves.length; i++) {\n vB += reserves[i] * prices[i];\n }\n if (vB <= 0n) throw new Error(\"Pool value is zero\");\n\n let t: bigint | undefined;\n for (let i = 0; i < offered.length; i++) {\n if (reserves[i] === 0n) continue;\n const cap = (offered[i] * vB) / reserves[i];\n t = t === undefined || cap < t ? cap : t;\n }\n if (t === undefined || t <= 0n) {\n throw new Error(\n \"A constant-sum deposit must offer every pool asset in proportion (asymmetric deposits are disallowed on-chain)\",\n );\n }\n\n const deltas = reserves.map((r) => (r * t! + vB - 1n) / vB); // ceil\n const nextTotalLp = (totalLp * (vB + t)) / vB; // floor\n const generatedLp = nextTotalLp - totalLp;\n if (generatedLp <= 0n) throw new Error(\"Deposit mints zero LP\");\n\n return {\n targetDeltaV: t,\n deltas,\n generatedLp,\n nextTotalLp,\n shareAfterDeposit: SharedPoolMath.getShare(generatedLp, nextTotalLp),\n };\n};\n\n/**\n * The per-asset amounts a pinned deposit needs when the user anchors on one\n * asset's amount: t from the anchor (`floor(anchor·V_b/r_anchor)`), every\n * delta ceil-pinned to it. Drives proportional auto-fill in deposit forms.\n */\nexport const pinnedDepositFromAnchor = (\n anchorIndex: number,\n anchorAmount: bigint,\n reserves: bigint[],\n prices: bigint[],\n): bigint[] => {\n if (reserves.length !== prices.length)\n throw new Error(\"reserves and prices must be aligned\");\n if (\n anchorIndex < 0 ||\n anchorIndex >= reserves.length ||\n reserves[anchorIndex] <= 0n\n )\n throw new Error(\"anchor asset has no reserve\");\n if (anchorAmount <= 0n) return reserves.map(() => 0n);\n\n let vB = 0n;\n for (let i = 0; i < reserves.length; i++) {\n vB += reserves[i] * prices[i];\n }\n if (vB <= 0n) throw new Error(\"Pool value is zero\");\n\n const t = (anchorAmount * vB) / reserves[anchorIndex];\n return reserves.map((r, i) =>\n i === anchorIndex ? anchorAmount : (r * t + vB - 1n) / vB,\n );\n};\n\nexport const calculateDepositN = (\n amounts: bigint[],\n reserves: bigint[],\n prices: bigint[],\n totalLp: bigint,\n) => {\n if (amounts.length !== reserves.length || reserves.length !== prices.length)\n throw new Error(\"amounts, reserves and prices must be aligned\");\n if (prices.some((p) => p <= 0n)) throw new Error(\"Prices must be positive\");\n // Zeros in a MIX are fine — offering a subset is the point of the N-asset\n // form. What's rejected is a negative amount, or offering nothing at all.\n if (amounts.some((a) => a < 0n) || amounts.every((a) => a === 0n))\n throw new Error(\n \"Deposit amounts must be non-negative, with at least one positive\",\n );\n\n let totalValue = 0n;\n let depositValue = 0n;\n for (let i = 0; i < amounts.length; i++) {\n totalValue += reserves[i] * prices[i];\n depositValue += amounts[i] * prices[i];\n }\n if (totalValue <= 0n || totalLp <= 0n)\n throw new Error(\"Not enough pool liquidity\");\n\n const generatedLp = (depositValue * totalLp) / totalValue;\n const nextTotalLp = totalLp + generatedLp;\n\n return {\n nextTotalLp,\n generatedLp,\n shareAfterDeposit: SharedPoolMath.getShare(generatedLp, nextTotalLp),\n };\n};\n\n/**\n * Outcome of {@link calculateZap}. Every array is aligned to `offered`.\n */\nexport type TZapOutcome = {\n /** Index of the offered asset swapped away; `undefined` when the basket already matches the reserves. */\n swapIndex: number | undefined;\n /** Amount of `offered[swapIndex]` swapped away. */\n swapInput: bigint;\n /** Amount of the other asset the swap yields. */\n swapOutput: bigint;\n /** Reserves after the swap — what the deposit pins against. */\n nextReserves: bigint[];\n /** `offered` after the swap: what is actually deposited. */\n depositBasket: bigint[];\n /** Per-asset ceil-pinned deposit. */\n deltas: bigint[];\n /** `depositBasket − deltas`: surplus returned to the user. */\n change: bigint[];\n targetDeltaV: bigint;\n generatedLp: bigint;\n nextTotalLp: bigint;\n shareAfterDeposit: Fraction;\n};\n\n/**\n * A zap on a 2-asset constant-sum pool: a non-proportional `offered` basket\n * is rebalanced by swapping part of the over-weighted asset, then deposited\n * under the target-pinned rule ({@link calculatePinnedDeposit}). The swap\n * amount `dx` is the one that leaves the post-swap basket proportional to\n * the post-swap reserves, so the pin consumes the whole basket up to\n * rounding. With `k = (1−fee)·p_X/p_Y`,\n *\n * (a_X − dx)/(r_X + dx) = (a_Y + k·dx)/(r_Y − k·dx)\n * ⇒ dx = (a_X·r_Y − a_Y·r_X) / (k·(r_X + a_X) + (r_Y + a_Y))\n *\n * (the dx² terms cancel). `dx` is floored and the swap leg follows\n * {@link getSwapOutput}; whatever imbalance rounding leaves comes back as\n * `change`.\n *\n * `fee` is the pool's fee for the swap direction — v4 splits bid and ask, so\n * the caller picks. Two assets only: with more, which assets to swap is an\n * allocation problem this formula does not address.\n */\nexport const calculateZap = (\n offered: bigint[],\n reserves: bigint[],\n prices: bigint[],\n totalLp: bigint,\n fee: TFractionLike,\n): TZapOutcome => {\n if (offered.length !== 2 || reserves.length !== 2 || prices.length !== 2)\n throw new Error(\"calculateZap supports exactly two assets\");\n if (prices.some((p) => p <= 0n)) throw new Error(\"Prices must be positive\");\n if (reserves.some((r) => r <= 0n))\n throw new Error(\"Reserves must be positive\");\n if (offered.some((a) => a < 0n) || offered.every((a) => a === 0n))\n throw new Error(\n \"Offered amounts must be non-negative, with at least one positive\",\n );\n if (totalLp <= 0n) throw new Error(\"Not enough pool liquidity\");\n\n const feeFraction = Fraction.asFraction(fee);\n if (feeFraction.lt(Fraction.ZERO) || feeFraction.gte(Fraction.ONE))\n throw new Error(\"fee must be [0,1)\");\n const feeNum = BigInt(feeFraction.numerator);\n const feeDen = BigInt(feeFraction.denominator);\n\n // Over-weighted side: compare a_0/r_0 against a_1/r_1 without division.\n const lhs = offered[0] * reserves[1];\n const rhs = offered[1] * reserves[0];\n const swapIndex = lhs > rhs ? 0 : lhs < rhs ? 1 : undefined;\n\n let swapInput = 0n;\n let swapOutput = 0n;\n const nextReserves = [...reserves];\n const depositBasket = [...offered];\n\n if (swapIndex !== undefined) {\n const x = swapIndex;\n const y = 1 - swapIndex;\n const [aX, aY] = [offered[x], offered[y]];\n const [rX, rY] = [reserves[x], reserves[y]];\n const [pX, pY] = [prices[x], prices[y]];\n\n // dx with k = (feeDen−feeNum)·pX / (feeDen·pY), cleared of denominators.\n const numerator = (aX * rY - aY * rX) * feeDen * pY;\n const denominator =\n (feeDen - feeNum) * pX * (rX + aX) + feeDen * pY * (rY + aY);\n swapInput = numerator / denominator;\n\n if (swapInput > 0n) {\n const inputValue = swapInput * pX;\n const feeValue = (inputValue * feeNum) / feeDen;\n swapOutput = (inputValue - feeValue) / pY;\n if (swapOutput >= rY)\n throw new Error(\n \"Pool too shallow: the rebalancing swap would drain it\",\n );\n\n nextReserves[x] = rX + swapInput;\n nextReserves[y] = rY - swapOutput;\n depositBasket[x] = aX - swapInput;\n depositBasket[y] = aY + swapOutput;\n }\n }\n\n if (depositBasket.some((a) => a <= 0n))\n throw new Error(\"Offered amount too small to zap into this pool\");\n\n const pinned = calculatePinnedDeposit(\n depositBasket,\n nextReserves,\n prices,\n totalLp,\n );\n\n return {\n swapIndex,\n swapInput,\n swapOutput,\n nextReserves,\n depositBasket,\n deltas: pinned.deltas,\n change: depositBasket.map((a, i) => a - pinned.deltas[i]),\n targetDeltaV: pinned.targetDeltaV,\n generatedLp: pinned.generatedLp,\n nextTotalLp: pinned.nextTotalLp,\n shareAfterDeposit: pinned.shareAfterDeposit,\n };\n};\n"],"mappings":"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","ignoreList":[]}
@@ -323,27 +323,27 @@ var getSwapOutput = exports.getSwapOutput = function getSwapOutput(outputMetadat
323
323
  };
324
324
 
325
325
  /**
326
- * Calculates the current price (exchange rate) of asset A in terms of asset B for a Stableswaps pool.
327
- * The price is derived from the Stableswaps curve equation and takes into account the amplification factor.
326
+ * The pool's marginal price as raw units of asset A per raw unit of asset B,
327
+ * |dx/dy| at the current reserves. This is the "ideal" price that swap price
328
+ * impact is measured against.
328
329
  *
329
- * The calculation uses the formula:
330
+ * Derived from the Stableswaps invariant 4A(x + y) + D = 4AD + D^3 / (4xy):
330
331
  * price = (xpA + (dR * aReserve) / bReserve) / (xpA + dR)
331
- * where xpA = (Ann * aReserve) / A_PRECISION and dR is derived from the sum invariant
332
+ * where xpA = 4 * laf * aReserve and dR = D^3 / (4 * aReserve * bReserve)
332
333
  *
333
334
  * @param {bigint} aReserve - The current reserve amount of asset A in the pool.
334
335
  * @param {bigint} bReserve - The current reserve amount of asset B in the pool.
335
336
  * @param {bigint} laf - The linear amplification factor of the pool.
336
- * @returns {Fraction} The price of asset A in terms of asset B as a Fraction.
337
+ * @returns {Fraction} Raw A per raw B at the current reserves.
337
338
  */
338
339
  function getPrice(aReserve, bReserve, laf) {
339
- // dx_0 / dx_1 only, however can have any number of coins in pool
340
- var ann = laf * 2n * A_PRECISION;
341
340
  var sumInvariant = getSumInvariant(laf, aReserve, bReserve) / RESERVE_PRECISION;
342
341
  // D / n^n with n = 2
343
342
  var dR = sumInvariant / 4n;
344
343
  dR = dR * sumInvariant / aReserve;
345
344
  dR = dR * sumInvariant / bReserve;
346
- var xpA = ann * aReserve / A_PRECISION;
345
+ // 4A is the amplification term of the on-chain invariant, A = laf.
346
+ var xpA = 4n * laf * aReserve;
347
347
  var p = new _fraction.Fraction(xpA + dR * aReserve / bReserve, xpA + dR);
348
348
  return p;
349
349
  }
@@ -1 +1 @@
1
- {"version":3,"file":"StableSwapsPool.js","names":["_asset","require","_index","_fraction","liquidityInvariant","assetA","assetB","linearAmplification","newSumInvariant","four_a","four_x_y","d_plus_one","d_cubed","d_plus_one_cubed","x_plus_y","sixteen_a_x_y","sixteen_a_x_y_x_plus_y","f1","f2","A_PRECISION","exports","RESERVE_PRECISION","FEE_PRECISION","getSumInvariant","a","x","y","Error","sum","d","ann","i","d_p","d_prev","getNewY","newX","aRaw","sumInvariant","yPrev","c","b","getFirstLp","laf","calculateLiquidity","aReserve","bReserve","totalLp","oldSumInvariant","newLpTokens","newTotalLpTokens","nextTotalLp","generatedLp","shareAfterDeposit","SharedPoolMath","getShare","aChange","bChange","actualDepositedA","actualDepositedB","getTokensForLp","lp","Fraction","quotient","getSwapOutput","outputMetadata","input","inputReserve","outputReserve","fee","protocolFee","roundOutputUp","asFraction","lt","ZERO","gte","ONE","combinedFee","add","nextInputReserve","newY","deltaYPrec","deltaY","totalFee","multiply","divide","totalProtocolFee","totalLpFee","output","subtract","safeOutput","numerator","denominator","nextOutputReserve","idealPrice","getPrice","actualPrice","priceImpact","lpFee","AssetAmount","nextSumInvariant","dR","xpA","p","getSwapInput","rawOutputF","sub","rawOutput"],"sources":["../../../src/PoolMath/StableSwapsPool.ts"],"sourcesContent":["import { AssetAmount, IAssetAmountMetadata } from \"@sundaeswap/asset\";\nimport { SharedPoolMath } from \"./index.js\";\nimport { Fraction, type TFractionLike } from \"@sundaeswap/fraction\";\n\n/**\n * Validates that a given sum invariant (D) satisfies the liquidity invariant equation\n * for the Stableswaps curve. This function checks if D is within the valid range by\n * evaluating the invariant function at D and D+1.\n *\n * The liquidity invariant ensures that the curve equation is satisfied:\n * 4A * 4xy * D + D^3 - (4xy * 4A * (x + y) + 4xy * D) should be <= 0 at D and > 0 at D+1\n *\n * @param {bigint} assetA - The reserve amount of asset A (already scaled by RESERVE_PRECISION).\n * @param {bigint} assetB - The reserve amount of asset B (already scaled by RESERVE_PRECISION).\n * @param {bigint} linearAmplification - The amplification coefficient for the pool.\n * @param {bigint} newSumInvariant - The proposed sum invariant (D) to validate.\n * @returns {boolean} True if the sum invariant satisfies the liquidity invariant equation, false otherwise.\n */\nexport function liquidityInvariant(\n assetA: bigint,\n assetB: bigint,\n linearAmplification: bigint,\n newSumInvariant: bigint,\n) {\n // 4 * A * 4 * (x*y) * D + D^3 - (4(x*y) * (4A(x + y) + D))\n // 4A * 4xy * D + D^3 - (4xy * 4a * (x + y) + 4xy * D)\n // 16Axy * D + D^3 - (16Axy * (x + y) + 4xy * D)\n const four_a = 4n * linearAmplification;\n const four_x_y = 4n * assetA * assetB;\n const d_plus_one = newSumInvariant + 1n;\n const d_cubed = newSumInvariant * newSumInvariant * newSumInvariant;\n const d_plus_one_cubed = d_plus_one * d_plus_one * d_plus_one;\n const x_plus_y = assetA + assetB;\n const sixteen_a_x_y = four_a * four_x_y;\n const sixteen_a_x_y_x_plus_y = sixteen_a_x_y * x_plus_y;\n const f1 =\n sixteen_a_x_y * newSumInvariant +\n d_cubed -\n (sixteen_a_x_y_x_plus_y + four_x_y * newSumInvariant);\n const f2 =\n sixteen_a_x_y * d_plus_one +\n d_plus_one_cubed -\n (sixteen_a_x_y_x_plus_y + four_x_y * d_plus_one);\n return f1 <= 0n && f2 > 0n;\n}\n\n/**\n * Precision factor for the amplification coefficient calculations.\n * Used to scale the amplification factor for more precise arithmetic operations.\n */\nexport const A_PRECISION: bigint = 200n;\n\n/**\n * Precision factor for reserve calculations in the Stableswaps curve.\n * Reserves are multiplied by this value to maintain precision during calculations.\n * This allows for accurate fractional calculations with integer arithmetic.\n */\nexport const RESERVE_PRECISION: bigint = 1_000_000_000_000n;\n\n/**\n * Precision factor for fee calculations, representing basis points.\n * A value of 10,000 means fees are calculated with 0.01% precision (1 basis point).\n */\nexport const FEE_PRECISION: bigint = 10_000n;\n\n/**\n * Calculates the sum invariant (D) for a Stableswaps pool using Newton's method.\n * The sum invariant represents the total value in the pool and is used to determine\n * the fair exchange rate between assets.\n *\n * This function iteratively solves for D in the Stableswaps invariant equation:\n * Ann * sum + D_p * 2 = Ann * D + D_p * 3\n * where D_p = D^3 / (4 * x * y) and Ann = A * n^n (with n=2)\n *\n * The iteration continues until convergence (difference <= 1) or fails after 255 iterations.\n *\n * @param {bigint} a - The amplification coefficient for the pool (will be scaled by A_PRECISION).\n * @param {bigint} x - The reserve amount of the first asset (will be scaled by RESERVE_PRECISION).\n * @param {bigint} y - The reserve amount of the second asset (will be scaled by RESERVE_PRECISION).\n * @returns {bigint} The calculated sum invariant (D) scaled by RESERVE_PRECISION.\n * @throws {Error} If the amplification coefficient is not positive.\n * @throws {Error} If convergence fails after 255 iterations.\n */\nexport function getSumInvariant(a: bigint, x: bigint, y: bigint): bigint {\n if (a <= 0n) {\n throw new Error(\"Amplification coefficient must be positive.\");\n }\n x = x * RESERVE_PRECISION;\n y = y * RESERVE_PRECISION;\n a = a * A_PRECISION;\n const sum: bigint = x + y;\n if (sum === 0n) {\n return 0n;\n }\n\n let d = sum;\n const ann = a * 2n;\n for (let i = 0; i < 255; i++) {\n const d_p = (d * d * d) / (4n * x * y);\n const d_prev = d;\n\n d =\n (((ann * sum) / 100n + d_p * 2n) * d) /\n (((ann - 100n) * d) / 100n + 3n * d_p);\n\n if (d > d_prev) {\n if (d - d_prev <= 1) {\n if (liquidityInvariant(x, y, a / A_PRECISION, d)) {\n return d;\n } else {\n return d - 1n;\n }\n }\n } else {\n if (d_prev - d <= 1) {\n if (liquidityInvariant(x, y, a / A_PRECISION, d)) {\n return d;\n } else {\n return d - 1n;\n }\n }\n }\n }\n throw new Error(\"Failed to converge on D value after 255 iterations.\");\n}\n\n/**\n * Calculates the new Y reserve value given a new X reserve value and the sum invariant.\n * This function uses Newton's method to iteratively solve for Y in the Stableswaps equation\n * while maintaining the pool's invariant (D).\n *\n * The function solves: Y^2 + (sum + (D * A_PRECISION) / (2 * Ann) - D) * Y - c = 0\n * where c is derived from D and the pool parameters.\n *\n * This is used during swaps to determine the output reserve after an input is added.\n *\n * @param {bigint} newX - The new reserve amount for asset X (will be scaled by RESERVE_PRECISION internally).\n * @param {bigint} aRaw - The raw amplification coefficient for the pool (will be scaled by A_PRECISION).\n * @param {bigint} sumInvariant - The pool's sum invariant (D), already scaled.\n * @returns {bigint} The calculated Y reserve value scaled by RESERVE_PRECISION.\n * @throws {Error} If convergence fails after 255 iterations.\n */\nexport function getNewY(\n newX: bigint,\n aRaw: bigint,\n sumInvariant: bigint,\n): bigint {\n newX = newX * RESERVE_PRECISION;\n const sum = newX;\n let yPrev: bigint;\n let c = sumInvariant;\n const ann = aRaw * A_PRECISION * 2n;\n\n c = (c * sumInvariant) / (newX * 2n);\n c = (c * sumInvariant * A_PRECISION) / 2n;\n c = c / (ann * 2n);\n const b = sum + (sumInvariant * A_PRECISION) / 2n / ann;\n let y = sumInvariant;\n for (let i = 0; i < 255; i++) {\n yPrev = y;\n y = (y * y + c) / (y * 2n + b - sumInvariant);\n if (y > yPrev) {\n if (y - yPrev <= 1n) {\n if (liquidityInvariant(newX, y, aRaw, sumInvariant)) {\n return y;\n } else {\n return y + 1n;\n }\n }\n } else {\n if (yPrev - y <= 1n) {\n if (liquidityInvariant(newX, y, aRaw, sumInvariant)) {\n return y;\n } else {\n return y + 1n;\n }\n }\n }\n }\n throw new Error(\"Failed to converge on y value after 255 iterations.\");\n}\n\n/**\n * Calculates the initial LP token amount for the first liquidity provision to a pool.\n * This is used when bootstrapping a new pool with initial reserves of assets A and B.\n *\n * The LP tokens minted are derived from the sum invariant (D) divided by the reserve precision,\n * effectively representing the pool's total value at inception.\n *\n * @param {bigint} a - The initial amount of token A being deposited.\n * @param {bigint} b - The initial amount of token B being deposited.\n * @param {bigint} laf - The linear amplification factor for the pool.\n * @returns {bigint} The amount of LP tokens to mint for the first liquidity provision.\n */\nexport const getFirstLp = (a: bigint, b: bigint, laf: bigint) =>\n getSumInvariant(laf, a, b) / RESERVE_PRECISION;\n\n/**\n * Calculates the liquidity parameters for adding liquidity to a Stableswaps pool.\n * This function supports mixed deposits where both assets can be deposited in any proportion.\n *\n * The calculation is based on the change in the sum invariant (D) before and after the deposit.\n * LP tokens are minted proportionally to the increase in D relative to the old D value.\n *\n * TODO: Investigate way to optimize actual deposited amounts\n *\n * @param {bigint} a - The amount of token A to deposit.\n * @param {bigint} b - The amount of token B to deposit.\n * @param {bigint} aReserve - The current reserve of token A in the pool.\n * @param {bigint} bReserve - The current reserve of token B in the pool.\n * @param {bigint} totalLp - The total LP tokens for the pool before the deposit.\n * @param {bigint} laf - The linear amplification factor of the pool.\n * @throws {Error} If the pool doesn't have enough liquidity (both reserves are zero).\n * @throws {Error} If both deposit amounts are zero.\n * @returns {Object} An object containing:\n * - nextTotalLp: The total LP tokens for the pool after the deposit.\n * - generatedLp: The amount of LP tokens generated by the deposit.\n * - shareAfterDeposit: The depositor's share of the pool after the deposit (as a Fraction).\n * - aChange: Always 0n for Stableswaps (no refund needed).\n * - bChange: Always 0n for Stableswaps (no refund needed).\n * - actualDepositedA: The actual amount of A deposited (always equal to input a).\n * - actualDepositedB: The actual amount of B deposited (always equal to input b).\n */\nexport const calculateLiquidity = (\n a: bigint,\n b: bigint,\n aReserve: bigint,\n bReserve: bigint,\n totalLp: bigint,\n laf: bigint,\n) => {\n if (aReserve === 0n && bReserve === 0n) {\n throw new Error(\"Not enough pool liquidity\");\n }\n\n if (a === 0n && b === 0n) {\n throw new Error(\"Cannot use a deposit asset amount of 0\");\n }\n\n const oldSumInvariant = getSumInvariant(laf, aReserve, bReserve);\n\n const newSumInvariant = getSumInvariant(laf, aReserve + a, bReserve + b);\n\n const newLpTokens =\n ((newSumInvariant - oldSumInvariant) * totalLp) / oldSumInvariant;\n\n const newTotalLpTokens = totalLp + newLpTokens;\n\n return {\n nextTotalLp: newTotalLpTokens,\n generatedLp: newLpTokens,\n shareAfterDeposit: SharedPoolMath.getShare(newLpTokens, newTotalLpTokens),\n aChange: 0n,\n bChange: 0n,\n actualDepositedA: a,\n actualDepositedB: b,\n };\n};\n\n/**\n * Calculates the token amounts that a given LP token amount represents when withdrawing\n * from a Stableswaps pool. The withdrawal is proportional to the LP tokens being redeemed\n * relative to the total LP supply.\n *\n * This uses a simple linear proportion: amount = (lp * reserve) / totalLp for each asset.\n *\n * @param {bigint} lp - The amount of LP tokens being redeemed.\n * @param {bigint} aReserve - The pool's current reserve amount of token A.\n * @param {bigint} bReserve - The pool's current reserve amount of token B.\n * @param {bigint} totalLp - The pool's total minted LP tokens currently in circulation.\n * @returns {SharedPoolMath.TPair} A tuple [a, b] containing the amounts of tokens A and B to withdraw.\n */\nexport const getTokensForLp = (\n lp: bigint,\n aReserve: bigint,\n bReserve: bigint,\n totalLp: bigint,\n): SharedPoolMath.TPair => [\n new Fraction(lp * aReserve, totalLp).quotient,\n new Fraction(lp * bReserve, totalLp).quotient,\n];\n\n/**\n * Represents the complete outcome of a swap operation in a Stableswaps pool.\n * Contains all relevant information about the swap including amounts, fees, updated reserves,\n * and price impact.\n */\nexport type TSwapOutcome = {\n /** The amount of input tokens being swapped */\n input: bigint;\n /** The amount of output tokens received (after all fees) */\n output: bigint;\n /** The portion of fees that goes to liquidity providers */\n lpFee: AssetAmount<IAssetAmountMetadata>;\n /** The portion of fees that goes to the protocol */\n protocolFee: AssetAmount<IAssetAmountMetadata>;\n /** The input asset reserve amount after the swap */\n nextInputReserve: bigint;\n /** The output asset reserve amount after the swap (excluding protocol fees) */\n nextOutputReserve: bigint;\n /** The pool's sum invariant (D) after the swap */\n nextSumInvariant: bigint;\n /** The price impact of the swap as a fraction (difference between ideal and actual price) */\n priceImpact: Fraction;\n};\n\n/**\n * Calculates the output amount and all swap parameters for a given input amount in a Stableswaps pool.\n * This function determines how many output tokens will be received for a given input, accounting for\n * the Stableswaps curve, LP fees, and protocol fees.\n *\n * The calculation process:\n * 1. Validates inputs and fees\n * 2. Calculates the current sum invariant (D)\n * 3. Determines the new Y value after adding input to X\n * 4. Calculates raw output and applies fees (LP + protocol)\n * 5. Computes price impact by comparing ideal vs actual execution price\n *\n * @param {bigint} input - The amount of input tokens to swap.\n * @param {bigint} inputReserve - The current reserve amount of the input token in the pool.\n * @param {bigint} outputReserve - The current reserve amount of the output token in the pool.\n * @param {TFractionLike} fee - The liquidity provider fee as a fraction (e.g., 0.003 for 0.3%).\n * @param {TFractionLike} protocolFee - The protocol fee as a fraction.\n * @param {bigint} laf - The linear amplification factor of the pool.\n * @param {boolean} [roundOutputUp] - Optional flag to round output up instead of down (default: false).\n * @returns {TSwapOutcome} The complete swap outcome including output, fees, reserves, and price impact.\n * @throws {Error} If input or reserves are not positive.\n * @throws {Error} If fee is not in the range [0, 1).\n * @throws {Error} If protocol fee is not in the range [0, 1).\n * @throws {Error} If combined fee is greater than or equal to 1.\n */\nexport const getSwapOutput = (\n outputMetadata: IAssetAmountMetadata,\n input: bigint,\n inputReserve: bigint,\n outputReserve: bigint,\n fee: TFractionLike,\n protocolFee: TFractionLike,\n laf: bigint,\n roundOutputUp?: boolean,\n): TSwapOutcome => {\n if (input <= 0 || inputReserve <= 0 || outputReserve <= 0)\n throw new Error(\"Input and reserves must be positive\");\n\n fee = Fraction.asFraction(fee);\n if (fee.lt(Fraction.ZERO) || fee.gte(Fraction.ONE))\n throw new Error(\"fee must be between 0 and 1\");\n\n protocolFee = Fraction.asFraction(protocolFee);\n if (protocolFee.lt(Fraction.ZERO) || protocolFee.gte(Fraction.ONE))\n throw new Error(\"protocolFee must be between 0 and 1\");\n\n const combinedFee = fee.add(protocolFee);\n if (combinedFee.gte(Fraction.ONE))\n throw new Error(\"Combined fee must be less than 1\");\n const sumInvariant = getSumInvariant(laf, inputReserve, outputReserve);\n const nextInputReserve = inputReserve + input;\n const newY = getNewY(nextInputReserve, laf, sumInvariant);\n\n const deltaYPrec = outputReserve * RESERVE_PRECISION - newY;\n const deltaY = new Fraction(deltaYPrec, RESERVE_PRECISION);\n const totalFee = combinedFee\n .multiply(FEE_PRECISION)\n .multiply(deltaY.quotient)\n .add(Fraction.asFraction(FEE_PRECISION - 1n))\n .divide(FEE_PRECISION).quotient;\n const totalProtocolFee = protocolFee\n .multiply(totalFee)\n .divide(combinedFee).quotient;\n const totalLpFee = totalFee - totalProtocolFee;\n const output = deltaY.subtract(totalFee);\n const safeOutput = roundOutputUp\n ? (output.numerator + output.denominator - 1n) / output.denominator\n : output.quotient;\n const nextOutputReserve = outputReserve - safeOutput - totalProtocolFee;\n\n // PRICEIMPACT: \"priceImpact\" is slightly misleadingly named in the industry as a whole\n // just by it's name, it would imply that it's the percentage difference between\n // the current price and the price after the swap, but it's actually the percentage\n // difference between the real price of your swap, and the price implied by the current\n // reserves; We got this wrong in v1, but this aligns it with the industry standard\n // Source: https://dailydefi.org/articles/price-impact-and-how-to-calculate/\n const idealPrice = getPrice(inputReserve, outputReserve, laf);\n const actualPrice = new Fraction(input, safeOutput);\n const priceImpact = Fraction.ONE.subtract(idealPrice.divide(actualPrice));\n return {\n input,\n output: safeOutput,\n lpFee: new AssetAmount(totalLpFee, outputMetadata),\n protocolFee: new AssetAmount(totalProtocolFee, outputMetadata),\n nextInputReserve,\n nextOutputReserve,\n nextSumInvariant: getSumInvariant(laf, nextInputReserve, nextOutputReserve),\n priceImpact,\n };\n};\n\n/**\n * Calculates the current price (exchange rate) of asset A in terms of asset B for a Stableswaps pool.\n * The price is derived from the Stableswaps curve equation and takes into account the amplification factor.\n *\n * The calculation uses the formula:\n * price = (xpA + (dR * aReserve) / bReserve) / (xpA + dR)\n * where xpA = (Ann * aReserve) / A_PRECISION and dR is derived from the sum invariant\n *\n * @param {bigint} aReserve - The current reserve amount of asset A in the pool.\n * @param {bigint} bReserve - The current reserve amount of asset B in the pool.\n * @param {bigint} laf - The linear amplification factor of the pool.\n * @returns {Fraction} The price of asset A in terms of asset B as a Fraction.\n */\nexport function getPrice(\n aReserve: bigint,\n bReserve: bigint,\n laf: bigint,\n): Fraction {\n // dx_0 / dx_1 only, however can have any number of coins in pool\n const ann = laf * 2n * A_PRECISION;\n const sumInvariant =\n getSumInvariant(laf, aReserve, bReserve) / RESERVE_PRECISION;\n // D / n^n with n = 2\n let dR = sumInvariant / 4n;\n dR = (dR * sumInvariant) / aReserve;\n dR = (dR * sumInvariant) / bReserve;\n const xpA = (ann * aReserve) / A_PRECISION;\n const p = new Fraction(xpA + (dR * aReserve) / bReserve, xpA + dR);\n return p;\n}\n\n/**\n * Calculates the required input amount and all swap parameters for a desired output amount in a Stableswaps pool.\n * This is the reverse operation of getSwapOutput - given how much you want to receive, it determines\n * how much you need to provide as input, accounting for fees and the Stableswaps curve.\n *\n * The calculation process:\n * 1. Validates inputs, fees, and output constraints\n * 2. Calculates raw output needed before fees\n * 3. Determines the new X value to achieve the desired Y reduction\n * 4. Calculates required input and separates LP and protocol fees\n * 5. Computes price impact by comparing ideal vs actual execution price\n *\n * @param {bigint} output - The desired amount of output tokens to receive.\n * @param {bigint} inputReserve - The current reserve amount of the input token in the pool.\n * @param {bigint} outputReserve - The current reserve amount of the output token in the pool.\n * @param {TFractionLike} fee - The liquidity provider fee as a fraction (e.g., 0.003 for 0.3%).\n * @param {TFractionLike} protocolFee - The protocol fee as a fraction.\n * @param {bigint} laf - The linear amplification factor of the pool.\n * @returns {TSwapOutcome} The complete swap outcome including required input, fees, reserves, and price impact.\n * @throws {Error} If output or reserves are not positive.\n * @throws {Error} If output is greater than or equal to the output reserve.\n * @throws {Error} If fee is not in the range [0, 1).\n * @throws {Error} If protocol fee is not in the range [0, 1).\n * @throws {Error} If combined fee is greater than or equal to 1.\n */\nexport const getSwapInput = (\n outputMetadata: IAssetAmountMetadata,\n output: bigint,\n inputReserve: bigint,\n outputReserve: bigint,\n fee: TFractionLike,\n protocolFee: TFractionLike,\n laf: bigint,\n): TSwapOutcome => {\n if (output <= 0 || inputReserve <= 0 || outputReserve <= 0)\n throw new Error(\"Output and reserves must be positive\");\n\n if (output >= outputReserve)\n throw new Error(\"Output must be less than output reserve\");\n\n fee = Fraction.asFraction(fee);\n if (fee.lt(Fraction.ZERO) || fee.gte(Fraction.ONE))\n throw new Error(\"fee must be [0,1)\");\n\n protocolFee = Fraction.asFraction(protocolFee);\n if (protocolFee.lt(Fraction.ZERO) || protocolFee.gte(Fraction.ONE))\n throw new Error(\"protocolFee must be between 0 and 1\");\n\n const combinedFee = fee.add(protocolFee);\n if (combinedFee.gte(Fraction.ONE))\n throw new Error(\"Combined fee must be less than 1\");\n\n // output = rawOutput * (1-fee)\n // rawOutput = output / (1-fee)\n const rawOutputF = Fraction.asFraction(output).divide(\n Fraction.ONE.sub(combinedFee),\n );\n const rawOutput =\n (rawOutputF.numerator + rawOutputF.denominator - 1n) /\n rawOutputF.denominator;\n const sumInvariant = getSumInvariant(laf, inputReserve, outputReserve);\n const newX = getNewY(outputReserve - rawOutput, laf, sumInvariant);\n const input =\n (newX - inputReserve * RESERVE_PRECISION + RESERVE_PRECISION - 1n) /\n RESERVE_PRECISION;\n\n const totalFee =\n (combinedFee.multiply(FEE_PRECISION).quotient * rawOutput +\n FEE_PRECISION -\n 1n) /\n FEE_PRECISION;\n const totalProtocolFee = protocolFee\n .multiply(totalFee)\n .divide(combinedFee).quotient;\n\n const totalLpFee = totalFee - totalProtocolFee;\n\n const nextInputReserve = inputReserve + input;\n const nextOutputReserve = outputReserve - output - totalProtocolFee;\n\n // See PRICEIMPACT\n const idealPrice = getPrice(inputReserve, outputReserve, laf);\n const actualPrice = new Fraction(input, output);\n const priceImpact = Fraction.ONE.subtract(idealPrice.divide(actualPrice));\n\n const nextSumInvariant = getSumInvariant(\n laf,\n nextInputReserve,\n nextOutputReserve,\n );\n\n return {\n input,\n output,\n lpFee: new AssetAmount(totalLpFee, outputMetadata),\n protocolFee: new AssetAmount(totalProtocolFee, outputMetadata),\n nextInputReserve,\n nextOutputReserve,\n priceImpact,\n nextSumInvariant,\n };\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"StableSwapsPool.js","names":["_asset","require","_index","_fraction","liquidityInvariant","assetA","assetB","linearAmplification","newSumInvariant","four_a","four_x_y","d_plus_one","d_cubed","d_plus_one_cubed","x_plus_y","sixteen_a_x_y","sixteen_a_x_y_x_plus_y","f1","f2","A_PRECISION","exports","RESERVE_PRECISION","FEE_PRECISION","getSumInvariant","a","x","y","Error","sum","d","ann","i","d_p","d_prev","getNewY","newX","aRaw","sumInvariant","yPrev","c","b","getFirstLp","laf","calculateLiquidity","aReserve","bReserve","totalLp","oldSumInvariant","newLpTokens","newTotalLpTokens","nextTotalLp","generatedLp","shareAfterDeposit","SharedPoolMath","getShare","aChange","bChange","actualDepositedA","actualDepositedB","getTokensForLp","lp","Fraction","quotient","getSwapOutput","outputMetadata","input","inputReserve","outputReserve","fee","protocolFee","roundOutputUp","asFraction","lt","ZERO","gte","ONE","combinedFee","add","nextInputReserve","newY","deltaYPrec","deltaY","totalFee","multiply","divide","totalProtocolFee","totalLpFee","output","subtract","safeOutput","numerator","denominator","nextOutputReserve","idealPrice","getPrice","actualPrice","priceImpact","lpFee","AssetAmount","nextSumInvariant","dR","xpA","p","getSwapInput","rawOutputF","sub","rawOutput"],"sources":["../../../src/PoolMath/StableSwapsPool.ts"],"sourcesContent":["import { AssetAmount, IAssetAmountMetadata } from \"@sundaeswap/asset\";\nimport { SharedPoolMath } from \"./index.js\";\nimport { Fraction, type TFractionLike } from \"@sundaeswap/fraction\";\n\n/**\n * Validates that a given sum invariant (D) satisfies the liquidity invariant equation\n * for the Stableswaps curve. This function checks if D is within the valid range by\n * evaluating the invariant function at D and D+1.\n *\n * The liquidity invariant ensures that the curve equation is satisfied:\n * 4A * 4xy * D + D^3 - (4xy * 4A * (x + y) + 4xy * D) should be <= 0 at D and > 0 at D+1\n *\n * @param {bigint} assetA - The reserve amount of asset A (already scaled by RESERVE_PRECISION).\n * @param {bigint} assetB - The reserve amount of asset B (already scaled by RESERVE_PRECISION).\n * @param {bigint} linearAmplification - The amplification coefficient for the pool.\n * @param {bigint} newSumInvariant - The proposed sum invariant (D) to validate.\n * @returns {boolean} True if the sum invariant satisfies the liquidity invariant equation, false otherwise.\n */\nexport function liquidityInvariant(\n assetA: bigint,\n assetB: bigint,\n linearAmplification: bigint,\n newSumInvariant: bigint,\n) {\n // 4 * A * 4 * (x*y) * D + D^3 - (4(x*y) * (4A(x + y) + D))\n // 4A * 4xy * D + D^3 - (4xy * 4a * (x + y) + 4xy * D)\n // 16Axy * D + D^3 - (16Axy * (x + y) + 4xy * D)\n const four_a = 4n * linearAmplification;\n const four_x_y = 4n * assetA * assetB;\n const d_plus_one = newSumInvariant + 1n;\n const d_cubed = newSumInvariant * newSumInvariant * newSumInvariant;\n const d_plus_one_cubed = d_plus_one * d_plus_one * d_plus_one;\n const x_plus_y = assetA + assetB;\n const sixteen_a_x_y = four_a * four_x_y;\n const sixteen_a_x_y_x_plus_y = sixteen_a_x_y * x_plus_y;\n const f1 =\n sixteen_a_x_y * newSumInvariant +\n d_cubed -\n (sixteen_a_x_y_x_plus_y + four_x_y * newSumInvariant);\n const f2 =\n sixteen_a_x_y * d_plus_one +\n d_plus_one_cubed -\n (sixteen_a_x_y_x_plus_y + four_x_y * d_plus_one);\n return f1 <= 0n && f2 > 0n;\n}\n\n/**\n * Precision factor for the amplification coefficient calculations.\n * Used to scale the amplification factor for more precise arithmetic operations.\n */\nexport const A_PRECISION: bigint = 200n;\n\n/**\n * Precision factor for reserve calculations in the Stableswaps curve.\n * Reserves are multiplied by this value to maintain precision during calculations.\n * This allows for accurate fractional calculations with integer arithmetic.\n */\nexport const RESERVE_PRECISION: bigint = 1_000_000_000_000n;\n\n/**\n * Precision factor for fee calculations, representing basis points.\n * A value of 10,000 means fees are calculated with 0.01% precision (1 basis point).\n */\nexport const FEE_PRECISION: bigint = 10_000n;\n\n/**\n * Calculates the sum invariant (D) for a Stableswaps pool using Newton's method.\n * The sum invariant represents the total value in the pool and is used to determine\n * the fair exchange rate between assets.\n *\n * This function iteratively solves for D in the Stableswaps invariant equation:\n * Ann * sum + D_p * 2 = Ann * D + D_p * 3\n * where D_p = D^3 / (4 * x * y) and Ann = A * n^n (with n=2)\n *\n * The iteration continues until convergence (difference <= 1) or fails after 255 iterations.\n *\n * @param {bigint} a - The amplification coefficient for the pool (will be scaled by A_PRECISION).\n * @param {bigint} x - The reserve amount of the first asset (will be scaled by RESERVE_PRECISION).\n * @param {bigint} y - The reserve amount of the second asset (will be scaled by RESERVE_PRECISION).\n * @returns {bigint} The calculated sum invariant (D) scaled by RESERVE_PRECISION.\n * @throws {Error} If the amplification coefficient is not positive.\n * @throws {Error} If convergence fails after 255 iterations.\n */\nexport function getSumInvariant(a: bigint, x: bigint, y: bigint): bigint {\n if (a <= 0n) {\n throw new Error(\"Amplification coefficient must be positive.\");\n }\n x = x * RESERVE_PRECISION;\n y = y * RESERVE_PRECISION;\n a = a * A_PRECISION;\n const sum: bigint = x + y;\n if (sum === 0n) {\n return 0n;\n }\n\n let d = sum;\n const ann = a * 2n;\n for (let i = 0; i < 255; i++) {\n const d_p = (d * d * d) / (4n * x * y);\n const d_prev = d;\n\n d =\n (((ann * sum) / 100n + d_p * 2n) * d) /\n (((ann - 100n) * d) / 100n + 3n * d_p);\n\n if (d > d_prev) {\n if (d - d_prev <= 1) {\n if (liquidityInvariant(x, y, a / A_PRECISION, d)) {\n return d;\n } else {\n return d - 1n;\n }\n }\n } else {\n if (d_prev - d <= 1) {\n if (liquidityInvariant(x, y, a / A_PRECISION, d)) {\n return d;\n } else {\n return d - 1n;\n }\n }\n }\n }\n throw new Error(\"Failed to converge on D value after 255 iterations.\");\n}\n\n/**\n * Calculates the new Y reserve value given a new X reserve value and the sum invariant.\n * This function uses Newton's method to iteratively solve for Y in the Stableswaps equation\n * while maintaining the pool's invariant (D).\n *\n * The function solves: Y^2 + (sum + (D * A_PRECISION) / (2 * Ann) - D) * Y - c = 0\n * where c is derived from D and the pool parameters.\n *\n * This is used during swaps to determine the output reserve after an input is added.\n *\n * @param {bigint} newX - The new reserve amount for asset X (will be scaled by RESERVE_PRECISION internally).\n * @param {bigint} aRaw - The raw amplification coefficient for the pool (will be scaled by A_PRECISION).\n * @param {bigint} sumInvariant - The pool's sum invariant (D), already scaled.\n * @returns {bigint} The calculated Y reserve value scaled by RESERVE_PRECISION.\n * @throws {Error} If convergence fails after 255 iterations.\n */\nexport function getNewY(\n newX: bigint,\n aRaw: bigint,\n sumInvariant: bigint,\n): bigint {\n newX = newX * RESERVE_PRECISION;\n const sum = newX;\n let yPrev: bigint;\n let c = sumInvariant;\n const ann = aRaw * A_PRECISION * 2n;\n\n c = (c * sumInvariant) / (newX * 2n);\n c = (c * sumInvariant * A_PRECISION) / 2n;\n c = c / (ann * 2n);\n const b = sum + (sumInvariant * A_PRECISION) / 2n / ann;\n let y = sumInvariant;\n for (let i = 0; i < 255; i++) {\n yPrev = y;\n y = (y * y + c) / (y * 2n + b - sumInvariant);\n if (y > yPrev) {\n if (y - yPrev <= 1n) {\n if (liquidityInvariant(newX, y, aRaw, sumInvariant)) {\n return y;\n } else {\n return y + 1n;\n }\n }\n } else {\n if (yPrev - y <= 1n) {\n if (liquidityInvariant(newX, y, aRaw, sumInvariant)) {\n return y;\n } else {\n return y + 1n;\n }\n }\n }\n }\n throw new Error(\"Failed to converge on y value after 255 iterations.\");\n}\n\n/**\n * Calculates the initial LP token amount for the first liquidity provision to a pool.\n * This is used when bootstrapping a new pool with initial reserves of assets A and B.\n *\n * The LP tokens minted are derived from the sum invariant (D) divided by the reserve precision,\n * effectively representing the pool's total value at inception.\n *\n * @param {bigint} a - The initial amount of token A being deposited.\n * @param {bigint} b - The initial amount of token B being deposited.\n * @param {bigint} laf - The linear amplification factor for the pool.\n * @returns {bigint} The amount of LP tokens to mint for the first liquidity provision.\n */\nexport const getFirstLp = (a: bigint, b: bigint, laf: bigint) =>\n getSumInvariant(laf, a, b) / RESERVE_PRECISION;\n\n/**\n * Calculates the liquidity parameters for adding liquidity to a Stableswaps pool.\n * This function supports mixed deposits where both assets can be deposited in any proportion.\n *\n * The calculation is based on the change in the sum invariant (D) before and after the deposit.\n * LP tokens are minted proportionally to the increase in D relative to the old D value.\n *\n * TODO: Investigate way to optimize actual deposited amounts\n *\n * @param {bigint} a - The amount of token A to deposit.\n * @param {bigint} b - The amount of token B to deposit.\n * @param {bigint} aReserve - The current reserve of token A in the pool.\n * @param {bigint} bReserve - The current reserve of token B in the pool.\n * @param {bigint} totalLp - The total LP tokens for the pool before the deposit.\n * @param {bigint} laf - The linear amplification factor of the pool.\n * @throws {Error} If the pool doesn't have enough liquidity (both reserves are zero).\n * @throws {Error} If both deposit amounts are zero.\n * @returns {Object} An object containing:\n * - nextTotalLp: The total LP tokens for the pool after the deposit.\n * - generatedLp: The amount of LP tokens generated by the deposit.\n * - shareAfterDeposit: The depositor's share of the pool after the deposit (as a Fraction).\n * - aChange: Always 0n for Stableswaps (no refund needed).\n * - bChange: Always 0n for Stableswaps (no refund needed).\n * - actualDepositedA: The actual amount of A deposited (always equal to input a).\n * - actualDepositedB: The actual amount of B deposited (always equal to input b).\n */\nexport const calculateLiquidity = (\n a: bigint,\n b: bigint,\n aReserve: bigint,\n bReserve: bigint,\n totalLp: bigint,\n laf: bigint,\n) => {\n if (aReserve === 0n && bReserve === 0n) {\n throw new Error(\"Not enough pool liquidity\");\n }\n\n if (a === 0n && b === 0n) {\n throw new Error(\"Cannot use a deposit asset amount of 0\");\n }\n\n const oldSumInvariant = getSumInvariant(laf, aReserve, bReserve);\n\n const newSumInvariant = getSumInvariant(laf, aReserve + a, bReserve + b);\n\n const newLpTokens =\n ((newSumInvariant - oldSumInvariant) * totalLp) / oldSumInvariant;\n\n const newTotalLpTokens = totalLp + newLpTokens;\n\n return {\n nextTotalLp: newTotalLpTokens,\n generatedLp: newLpTokens,\n shareAfterDeposit: SharedPoolMath.getShare(newLpTokens, newTotalLpTokens),\n aChange: 0n,\n bChange: 0n,\n actualDepositedA: a,\n actualDepositedB: b,\n };\n};\n\n/**\n * Calculates the token amounts that a given LP token amount represents when withdrawing\n * from a Stableswaps pool. The withdrawal is proportional to the LP tokens being redeemed\n * relative to the total LP supply.\n *\n * This uses a simple linear proportion: amount = (lp * reserve) / totalLp for each asset.\n *\n * @param {bigint} lp - The amount of LP tokens being redeemed.\n * @param {bigint} aReserve - The pool's current reserve amount of token A.\n * @param {bigint} bReserve - The pool's current reserve amount of token B.\n * @param {bigint} totalLp - The pool's total minted LP tokens currently in circulation.\n * @returns {SharedPoolMath.TPair} A tuple [a, b] containing the amounts of tokens A and B to withdraw.\n */\nexport const getTokensForLp = (\n lp: bigint,\n aReserve: bigint,\n bReserve: bigint,\n totalLp: bigint,\n): SharedPoolMath.TPair => [\n new Fraction(lp * aReserve, totalLp).quotient,\n new Fraction(lp * bReserve, totalLp).quotient,\n];\n\n/**\n * Represents the complete outcome of a swap operation in a Stableswaps pool.\n * Contains all relevant information about the swap including amounts, fees, updated reserves,\n * and price impact.\n */\nexport type TSwapOutcome = {\n /** The amount of input tokens being swapped */\n input: bigint;\n /** The amount of output tokens received (after all fees) */\n output: bigint;\n /** The portion of fees that goes to liquidity providers */\n lpFee: AssetAmount<IAssetAmountMetadata>;\n /** The portion of fees that goes to the protocol */\n protocolFee: AssetAmount<IAssetAmountMetadata>;\n /** The input asset reserve amount after the swap */\n nextInputReserve: bigint;\n /** The output asset reserve amount after the swap (excluding protocol fees) */\n nextOutputReserve: bigint;\n /** The pool's sum invariant (D) after the swap */\n nextSumInvariant: bigint;\n /** The price impact of the swap as a fraction (difference between ideal and actual price) */\n priceImpact: Fraction;\n};\n\n/**\n * Calculates the output amount and all swap parameters for a given input amount in a Stableswaps pool.\n * This function determines how many output tokens will be received for a given input, accounting for\n * the Stableswaps curve, LP fees, and protocol fees.\n *\n * The calculation process:\n * 1. Validates inputs and fees\n * 2. Calculates the current sum invariant (D)\n * 3. Determines the new Y value after adding input to X\n * 4. Calculates raw output and applies fees (LP + protocol)\n * 5. Computes price impact by comparing ideal vs actual execution price\n *\n * @param {bigint} input - The amount of input tokens to swap.\n * @param {bigint} inputReserve - The current reserve amount of the input token in the pool.\n * @param {bigint} outputReserve - The current reserve amount of the output token in the pool.\n * @param {TFractionLike} fee - The liquidity provider fee as a fraction (e.g., 0.003 for 0.3%).\n * @param {TFractionLike} protocolFee - The protocol fee as a fraction.\n * @param {bigint} laf - The linear amplification factor of the pool.\n * @param {boolean} [roundOutputUp] - Optional flag to round output up instead of down (default: false).\n * @returns {TSwapOutcome} The complete swap outcome including output, fees, reserves, and price impact.\n * @throws {Error} If input or reserves are not positive.\n * @throws {Error} If fee is not in the range [0, 1).\n * @throws {Error} If protocol fee is not in the range [0, 1).\n * @throws {Error} If combined fee is greater than or equal to 1.\n */\nexport const getSwapOutput = (\n outputMetadata: IAssetAmountMetadata,\n input: bigint,\n inputReserve: bigint,\n outputReserve: bigint,\n fee: TFractionLike,\n protocolFee: TFractionLike,\n laf: bigint,\n roundOutputUp?: boolean,\n): TSwapOutcome => {\n if (input <= 0 || inputReserve <= 0 || outputReserve <= 0)\n throw new Error(\"Input and reserves must be positive\");\n\n fee = Fraction.asFraction(fee);\n if (fee.lt(Fraction.ZERO) || fee.gte(Fraction.ONE))\n throw new Error(\"fee must be between 0 and 1\");\n\n protocolFee = Fraction.asFraction(protocolFee);\n if (protocolFee.lt(Fraction.ZERO) || protocolFee.gte(Fraction.ONE))\n throw new Error(\"protocolFee must be between 0 and 1\");\n\n const combinedFee = fee.add(protocolFee);\n if (combinedFee.gte(Fraction.ONE))\n throw new Error(\"Combined fee must be less than 1\");\n const sumInvariant = getSumInvariant(laf, inputReserve, outputReserve);\n const nextInputReserve = inputReserve + input;\n const newY = getNewY(nextInputReserve, laf, sumInvariant);\n\n const deltaYPrec = outputReserve * RESERVE_PRECISION - newY;\n const deltaY = new Fraction(deltaYPrec, RESERVE_PRECISION);\n const totalFee = combinedFee\n .multiply(FEE_PRECISION)\n .multiply(deltaY.quotient)\n .add(Fraction.asFraction(FEE_PRECISION - 1n))\n .divide(FEE_PRECISION).quotient;\n const totalProtocolFee = protocolFee\n .multiply(totalFee)\n .divide(combinedFee).quotient;\n const totalLpFee = totalFee - totalProtocolFee;\n const output = deltaY.subtract(totalFee);\n const safeOutput = roundOutputUp\n ? (output.numerator + output.denominator - 1n) / output.denominator\n : output.quotient;\n const nextOutputReserve = outputReserve - safeOutput - totalProtocolFee;\n\n // PRICEIMPACT: \"priceImpact\" is slightly misleadingly named in the industry as a whole\n // just by it's name, it would imply that it's the percentage difference between\n // the current price and the price after the swap, but it's actually the percentage\n // difference between the real price of your swap, and the price implied by the current\n // reserves; We got this wrong in v1, but this aligns it with the industry standard\n // Source: https://dailydefi.org/articles/price-impact-and-how-to-calculate/\n const idealPrice = getPrice(inputReserve, outputReserve, laf);\n const actualPrice = new Fraction(input, safeOutput);\n const priceImpact = Fraction.ONE.subtract(idealPrice.divide(actualPrice));\n return {\n input,\n output: safeOutput,\n lpFee: new AssetAmount(totalLpFee, outputMetadata),\n protocolFee: new AssetAmount(totalProtocolFee, outputMetadata),\n nextInputReserve,\n nextOutputReserve,\n nextSumInvariant: getSumInvariant(laf, nextInputReserve, nextOutputReserve),\n priceImpact,\n };\n};\n\n/**\n * The pool's marginal price as raw units of asset A per raw unit of asset B,\n * |dx/dy| at the current reserves. This is the \"ideal\" price that swap price\n * impact is measured against.\n *\n * Derived from the Stableswaps invariant 4A(x + y) + D = 4AD + D^3 / (4xy):\n * price = (xpA + (dR * aReserve) / bReserve) / (xpA + dR)\n * where xpA = 4 * laf * aReserve and dR = D^3 / (4 * aReserve * bReserve)\n *\n * @param {bigint} aReserve - The current reserve amount of asset A in the pool.\n * @param {bigint} bReserve - The current reserve amount of asset B in the pool.\n * @param {bigint} laf - The linear amplification factor of the pool.\n * @returns {Fraction} Raw A per raw B at the current reserves.\n */\nexport function getPrice(\n aReserve: bigint,\n bReserve: bigint,\n laf: bigint,\n): Fraction {\n const sumInvariant =\n getSumInvariant(laf, aReserve, bReserve) / RESERVE_PRECISION;\n // D / n^n with n = 2\n let dR = sumInvariant / 4n;\n dR = (dR * sumInvariant) / aReserve;\n dR = (dR * sumInvariant) / bReserve;\n // 4A is the amplification term of the on-chain invariant, A = laf.\n const xpA = 4n * laf * aReserve;\n const p = new Fraction(xpA + (dR * aReserve) / bReserve, xpA + dR);\n return p;\n}\n\n/**\n * Calculates the required input amount and all swap parameters for a desired output amount in a Stableswaps pool.\n * This is the reverse operation of getSwapOutput - given how much you want to receive, it determines\n * how much you need to provide as input, accounting for fees and the Stableswaps curve.\n *\n * The calculation process:\n * 1. Validates inputs, fees, and output constraints\n * 2. Calculates raw output needed before fees\n * 3. Determines the new X value to achieve the desired Y reduction\n * 4. Calculates required input and separates LP and protocol fees\n * 5. Computes price impact by comparing ideal vs actual execution price\n *\n * @param {bigint} output - The desired amount of output tokens to receive.\n * @param {bigint} inputReserve - The current reserve amount of the input token in the pool.\n * @param {bigint} outputReserve - The current reserve amount of the output token in the pool.\n * @param {TFractionLike} fee - The liquidity provider fee as a fraction (e.g., 0.003 for 0.3%).\n * @param {TFractionLike} protocolFee - The protocol fee as a fraction.\n * @param {bigint} laf - The linear amplification factor of the pool.\n * @returns {TSwapOutcome} The complete swap outcome including required input, fees, reserves, and price impact.\n * @throws {Error} If output or reserves are not positive.\n * @throws {Error} If output is greater than or equal to the output reserve.\n * @throws {Error} If fee is not in the range [0, 1).\n * @throws {Error} If protocol fee is not in the range [0, 1).\n * @throws {Error} If combined fee is greater than or equal to 1.\n */\nexport const getSwapInput = (\n outputMetadata: IAssetAmountMetadata,\n output: bigint,\n inputReserve: bigint,\n outputReserve: bigint,\n fee: TFractionLike,\n protocolFee: TFractionLike,\n laf: bigint,\n): TSwapOutcome => {\n if (output <= 0 || inputReserve <= 0 || outputReserve <= 0)\n throw new Error(\"Output and reserves must be positive\");\n\n if (output >= outputReserve)\n throw new Error(\"Output must be less than output reserve\");\n\n fee = Fraction.asFraction(fee);\n if (fee.lt(Fraction.ZERO) || fee.gte(Fraction.ONE))\n throw new Error(\"fee must be [0,1)\");\n\n protocolFee = Fraction.asFraction(protocolFee);\n if (protocolFee.lt(Fraction.ZERO) || protocolFee.gte(Fraction.ONE))\n throw new Error(\"protocolFee must be between 0 and 1\");\n\n const combinedFee = fee.add(protocolFee);\n if (combinedFee.gte(Fraction.ONE))\n throw new Error(\"Combined fee must be less than 1\");\n\n // output = rawOutput * (1-fee)\n // rawOutput = output / (1-fee)\n const rawOutputF = Fraction.asFraction(output).divide(\n Fraction.ONE.sub(combinedFee),\n );\n const rawOutput =\n (rawOutputF.numerator + rawOutputF.denominator - 1n) /\n rawOutputF.denominator;\n const sumInvariant = getSumInvariant(laf, inputReserve, outputReserve);\n const newX = getNewY(outputReserve - rawOutput, laf, sumInvariant);\n const input =\n (newX - inputReserve * RESERVE_PRECISION + RESERVE_PRECISION - 1n) /\n RESERVE_PRECISION;\n\n const totalFee =\n (combinedFee.multiply(FEE_PRECISION).quotient * rawOutput +\n FEE_PRECISION -\n 1n) /\n FEE_PRECISION;\n const totalProtocolFee = protocolFee\n .multiply(totalFee)\n .divide(combinedFee).quotient;\n\n const totalLpFee = totalFee - totalProtocolFee;\n\n const nextInputReserve = inputReserve + input;\n const nextOutputReserve = outputReserve - output - totalProtocolFee;\n\n // See PRICEIMPACT\n const idealPrice = getPrice(inputReserve, outputReserve, laf);\n const actualPrice = new Fraction(input, output);\n const priceImpact = Fraction.ONE.subtract(idealPrice.divide(actualPrice));\n\n const nextSumInvariant = getSumInvariant(\n laf,\n nextInputReserve,\n nextOutputReserve,\n );\n\n return {\n input,\n output,\n lpFee: new AssetAmount(totalLpFee, outputMetadata),\n protocolFee: new AssetAmount(totalProtocolFee, outputMetadata),\n nextInputReserve,\n nextOutputReserve,\n priceImpact,\n nextSumInvariant,\n };\n};\n"],"mappings":"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","ignoreList":[]}
@@ -263,4 +263,85 @@ export const calculateDepositN = (amounts, reserves, prices, totalLp) => {
263
263
  shareAfterDeposit: SharedPoolMath.getShare(generatedLp, nextTotalLp)
264
264
  };
265
265
  };
266
+
267
+ /**
268
+ * Outcome of {@link calculateZap}. Every array is aligned to `offered`.
269
+ */
270
+
271
+ /**
272
+ * A zap on a 2-asset constant-sum pool: a non-proportional `offered` basket
273
+ * is rebalanced by swapping part of the over-weighted asset, then deposited
274
+ * under the target-pinned rule ({@link calculatePinnedDeposit}). The swap
275
+ * amount `dx` is the one that leaves the post-swap basket proportional to
276
+ * the post-swap reserves, so the pin consumes the whole basket up to
277
+ * rounding. With `k = (1−fee)·p_X/p_Y`,
278
+ *
279
+ * (a_X − dx)/(r_X + dx) = (a_Y + k·dx)/(r_Y − k·dx)
280
+ * ⇒ dx = (a_X·r_Y − a_Y·r_X) / (k·(r_X + a_X) + (r_Y + a_Y))
281
+ *
282
+ * (the dx² terms cancel). `dx` is floored and the swap leg follows
283
+ * {@link getSwapOutput}; whatever imbalance rounding leaves comes back as
284
+ * `change`.
285
+ *
286
+ * `fee` is the pool's fee for the swap direction — v4 splits bid and ask, so
287
+ * the caller picks. Two assets only: with more, which assets to swap is an
288
+ * allocation problem this formula does not address.
289
+ */
290
+ export const calculateZap = (offered, reserves, prices, totalLp, fee) => {
291
+ if (offered.length !== 2 || reserves.length !== 2 || prices.length !== 2) throw new Error("calculateZap supports exactly two assets");
292
+ if (prices.some(p => p <= 0n)) throw new Error("Prices must be positive");
293
+ if (reserves.some(r => r <= 0n)) throw new Error("Reserves must be positive");
294
+ if (offered.some(a => a < 0n) || offered.every(a => a === 0n)) throw new Error("Offered amounts must be non-negative, with at least one positive");
295
+ if (totalLp <= 0n) throw new Error("Not enough pool liquidity");
296
+ const feeFraction = Fraction.asFraction(fee);
297
+ if (feeFraction.lt(Fraction.ZERO) || feeFraction.gte(Fraction.ONE)) throw new Error("fee must be [0,1)");
298
+ const feeNum = BigInt(feeFraction.numerator);
299
+ const feeDen = BigInt(feeFraction.denominator);
300
+
301
+ // Over-weighted side: compare a_0/r_0 against a_1/r_1 without division.
302
+ const lhs = offered[0] * reserves[1];
303
+ const rhs = offered[1] * reserves[0];
304
+ const swapIndex = lhs > rhs ? 0 : lhs < rhs ? 1 : undefined;
305
+ let swapInput = 0n;
306
+ let swapOutput = 0n;
307
+ const nextReserves = [...reserves];
308
+ const depositBasket = [...offered];
309
+ if (swapIndex !== undefined) {
310
+ const x = swapIndex;
311
+ const y = 1 - swapIndex;
312
+ const [aX, aY] = [offered[x], offered[y]];
313
+ const [rX, rY] = [reserves[x], reserves[y]];
314
+ const [pX, pY] = [prices[x], prices[y]];
315
+
316
+ // dx with k = (feeDen−feeNum)·pX / (feeDen·pY), cleared of denominators.
317
+ const numerator = (aX * rY - aY * rX) * feeDen * pY;
318
+ const denominator = (feeDen - feeNum) * pX * (rX + aX) + feeDen * pY * (rY + aY);
319
+ swapInput = numerator / denominator;
320
+ if (swapInput > 0n) {
321
+ const inputValue = swapInput * pX;
322
+ const feeValue = inputValue * feeNum / feeDen;
323
+ swapOutput = (inputValue - feeValue) / pY;
324
+ if (swapOutput >= rY) throw new Error("Pool too shallow: the rebalancing swap would drain it");
325
+ nextReserves[x] = rX + swapInput;
326
+ nextReserves[y] = rY - swapOutput;
327
+ depositBasket[x] = aX - swapInput;
328
+ depositBasket[y] = aY + swapOutput;
329
+ }
330
+ }
331
+ if (depositBasket.some(a => a <= 0n)) throw new Error("Offered amount too small to zap into this pool");
332
+ const pinned = calculatePinnedDeposit(depositBasket, nextReserves, prices, totalLp);
333
+ return {
334
+ swapIndex,
335
+ swapInput,
336
+ swapOutput,
337
+ nextReserves,
338
+ depositBasket,
339
+ deltas: pinned.deltas,
340
+ change: depositBasket.map((a, i) => a - pinned.deltas[i]),
341
+ targetDeltaV: pinned.targetDeltaV,
342
+ generatedLp: pinned.generatedLp,
343
+ nextTotalLp: pinned.nextTotalLp,
344
+ shareAfterDeposit: pinned.shareAfterDeposit
345
+ };
346
+ };
266
347
  //# sourceMappingURL=ConstantSumPool.js.map