@sundaeswap/math 0.2.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/PoolMath/ConcentratedLiquidityPool.js +214 -0
- package/dist/cjs/PoolMath/ConcentratedLiquidityPool.js.map +1 -0
- package/dist/cjs/PoolMath/ConstantSumPool.js +284 -0
- package/dist/cjs/PoolMath/ConstantSumPool.js.map +1 -0
- package/dist/cjs/PoolMath/V4StableswapPool.js +529 -0
- package/dist/cjs/PoolMath/V4StableswapPool.js.map +1 -0
- package/dist/cjs/PoolMath/index.js +7 -1
- package/dist/cjs/PoolMath/index.js.map +1 -1
- package/dist/esm/PoolMath/ConcentratedLiquidityPool.js +181 -0
- package/dist/esm/PoolMath/ConcentratedLiquidityPool.js.map +1 -0
- package/dist/esm/PoolMath/ConstantSumPool.js +266 -0
- package/dist/esm/PoolMath/ConstantSumPool.js.map +1 -0
- package/dist/esm/PoolMath/V4StableswapPool.js +495 -0
- package/dist/esm/PoolMath/V4StableswapPool.js.map +1 -0
- package/dist/esm/PoolMath/index.js +3 -0
- package/dist/esm/PoolMath/index.js.map +1 -1
- package/dist/types/PoolMath/ConcentratedLiquidityPool.d.ts +60 -0
- package/dist/types/PoolMath/ConcentratedLiquidityPool.d.ts.map +1 -0
- package/dist/types/PoolMath/ConstantSumPool.d.ts +133 -0
- package/dist/types/PoolMath/ConstantSumPool.d.ts.map +1 -0
- package/dist/types/PoolMath/V4StableswapPool.d.ts +221 -0
- package/dist/types/PoolMath/V4StableswapPool.d.ts.map +1 -0
- package/dist/types/PoolMath/index.d.ts +3 -0
- package/dist/types/PoolMath/index.d.ts.map +1 -1
- package/dist/types/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/PoolMath/ConcentratedLiquidityPool.ts +275 -0
- package/src/PoolMath/ConstantSumPool.ts +371 -0
- package/src/PoolMath/V4StableswapPool.ts +638 -0
- package/src/PoolMath/__tests__/ConcentratedLiquidityPool.test.ts +225 -0
- package/src/PoolMath/__tests__/ConstantSumPool.test.ts +322 -0
- package/src/PoolMath/__tests__/V4StableswapPool.test.ts +688 -0
- package/src/PoolMath/index.ts +3 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { AssetAmount, IAssetAmountMetadata } from "@sundaeswap/asset";
|
|
2
|
+
import { Fraction, type TFractionLike } from "@sundaeswap/fraction";
|
|
3
|
+
/**
|
|
4
|
+
* Holds the calculated outcome of a concentrated-liquidity swap. Mirrors
|
|
5
|
+
* {@link ConstantProductPool.TSwapOutcome} so it flows through the same generic
|
|
6
|
+
* swap-outcome consumers.
|
|
7
|
+
*/
|
|
8
|
+
export type TSwapOutcome = {
|
|
9
|
+
input: bigint;
|
|
10
|
+
output: bigint;
|
|
11
|
+
lpFee: AssetAmount<IAssetAmountMetadata>;
|
|
12
|
+
nextInputReserve: bigint;
|
|
13
|
+
nextOutputReserve: bigint;
|
|
14
|
+
priceImpact: Fraction;
|
|
15
|
+
};
|
|
16
|
+
/** A sqrt-price bound from the CL config, as an exact rational `[num, den]`. */
|
|
17
|
+
export type TSqrtPrice = [bigint, bigint];
|
|
18
|
+
/**
|
|
19
|
+
* Calculate the swap outcome for a concentrated-liquidity pool.
|
|
20
|
+
*
|
|
21
|
+
* @param inputMetadata Metadata for the supplied (input) asset — used for the fee AssetAmount.
|
|
22
|
+
* @param input The pre-fee amount of the input asset being swapped.
|
|
23
|
+
* @param aReserve The pool's raw reserve of asset A.
|
|
24
|
+
* @param bReserve The pool's raw reserve of asset B.
|
|
25
|
+
* @param totalLp The pool's total LP supply (the virtual liquidity `L`).
|
|
26
|
+
* @param sqrtPriceA The lower sqrt-price bound `[num, den]` from the CL config.
|
|
27
|
+
* @param sqrtPriceB The upper sqrt-price bound `[num, den]` from the CL config.
|
|
28
|
+
* @param fee The liquidity-provider fee (plus protocol fee) as a fraction.
|
|
29
|
+
* @param isAInput True when asset A is the supplied asset (A→B swap).
|
|
30
|
+
* @returns The swap details in the shared {@link TSwapOutcome} shape.
|
|
31
|
+
*/
|
|
32
|
+
export declare const getSwapOutput: (inputMetadata: IAssetAmountMetadata, input: bigint, aReserve: bigint, bReserve: bigint, totalLp: bigint, sqrtPriceA: TSqrtPrice, sqrtPriceB: TSqrtPrice, fee: TFractionLike, isAInput: boolean) => TSwapOutcome;
|
|
33
|
+
/**
|
|
34
|
+
* Calculate the minimal input required to receive a given output — the inverse
|
|
35
|
+
* of {@link getSwapOutput}. The forward swap is linear-fractional in the
|
|
36
|
+
* effective input, so it inverts in closed form; a short correction loop
|
|
37
|
+
* absorbs the fee floor and integer rounding so the result is the exact minimal
|
|
38
|
+
* input whose forward swap yields at least `output`.
|
|
39
|
+
*/
|
|
40
|
+
export declare const getSwapInput: (inputMetadata: IAssetAmountMetadata, output: bigint, aReserve: bigint, bReserve: bigint, totalLp: bigint, sqrtPriceA: TSqrtPrice, sqrtPriceB: TSqrtPrice, fee: TFractionLike, isAInput: boolean) => TSwapOutcome;
|
|
41
|
+
/**
|
|
42
|
+
* Deposit LP estimate for a concentrated-liquidity pool. CL deposits reuse the
|
|
43
|
+
* constant-product *proportional* pinning: minting by the scarcest offered
|
|
44
|
+
* asset and ceil-pinning the reserve deltas gives, per asset,
|
|
45
|
+
* `a1·L0 ≥ a0·L1` and `b1·L0 ≥ b0·L1` — and those two bounds multiply to
|
|
46
|
+
* exactly the on-chain CL non-swap invariant `va1·vb1·L0² ≥ va0·vb0·L1²`
|
|
47
|
+
* (`cl_check.ak`). So the proportional deposit is always chain-valid; excess of
|
|
48
|
+
* either asset is refunded via aChange/bChange. This mirrors the scooper's
|
|
49
|
+
* `resolve_cl_deposit` (which likewise reuses the CP pinning).
|
|
50
|
+
*/
|
|
51
|
+
export declare const calculateLiquidity: (a: bigint, b: bigint, aReserve: bigint, bReserve: bigint, totalLp: bigint) => {
|
|
52
|
+
nextTotalLp: bigint;
|
|
53
|
+
generatedLp: bigint;
|
|
54
|
+
shareAfterDeposit: Fraction;
|
|
55
|
+
bChange: bigint;
|
|
56
|
+
aChange: bigint;
|
|
57
|
+
actualDepositedA: bigint;
|
|
58
|
+
actualDepositedB: bigint;
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=ConcentratedLiquidityPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConcentratedLiquidityPool.d.ts","sourceRoot":"","sources":["../../../src/PoolMath/ConcentratedLiquidityPool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIpE;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,CAAC,oBAAoB,CAAC,CAAC;IACzC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,QAAQ,CAAC;CACvB,CAAC;AAEF,gFAAgF;AAChF,MAAM,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AA2D1C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,aAAa,kBACT,oBAAoB,SAC5B,MAAM,YACH,MAAM,YACN,MAAM,WACP,MAAM,cACH,UAAU,cACV,UAAU,OACjB,aAAa,YACR,OAAO,KAChB,YAuDF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,kBACR,oBAAoB,UAC3B,MAAM,YACJ,MAAM,YACN,MAAM,WACP,MAAM,cACH,UAAU,cACV,UAAU,OACjB,aAAa,YACR,OAAO,KAChB,YA+EF,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,MAC1B,MAAM,KACN,MAAM,YACC,MAAM,YACN,MAAM,WACP,MAAM;;;;;;;;CAC6D,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { AssetAmount, IAssetAmountMetadata } from "@sundaeswap/asset";
|
|
2
|
+
import { Fraction, type TFractionLike } from "@sundaeswap/fraction";
|
|
3
|
+
/**
|
|
4
|
+
* Holds the calculated outcome of a constant-sum swap. Mirrors
|
|
5
|
+
* {@link ConstantProductPool.TSwapOutcome} so both can flow through the same
|
|
6
|
+
* generic swap-outcome consumers.
|
|
7
|
+
*/
|
|
8
|
+
export type TSwapOutcome = {
|
|
9
|
+
input: bigint;
|
|
10
|
+
output: bigint;
|
|
11
|
+
lpFee: AssetAmount<IAssetAmountMetadata>;
|
|
12
|
+
nextInputReserve: bigint;
|
|
13
|
+
nextOutputReserve: bigint;
|
|
14
|
+
priceImpact: Fraction;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Calculate the swap outcome for a constant-sum (fixed-price) pool — the
|
|
18
|
+
* invariant used by Sundae v4 stable/pegged pools. Unlike constant product,
|
|
19
|
+
* the exchange rate is fixed by the pool's per-asset `prices`: the input is
|
|
20
|
+
* converted to "value" at `priceIn`, the fee is taken off that value, and the
|
|
21
|
+
* remainder is converted to the output asset at `priceOut`. The result is
|
|
22
|
+
* capped at the output reserve (you can't take more than the pool holds).
|
|
23
|
+
*
|
|
24
|
+
* Matches the scooper's `cs_swap_result`:
|
|
25
|
+
* output = floor((input·priceIn − floor(input·priceIn·fee)) / priceOut)
|
|
26
|
+
*
|
|
27
|
+
* @param inputMetadata Metadata for the supplied (input) asset — used for the fee AssetAmount.
|
|
28
|
+
* @param input The amount of the input asset being swapped.
|
|
29
|
+
* @param inputReserve The pool's reserve of the input asset.
|
|
30
|
+
* @param outputReserve The pool's reserve of the output asset.
|
|
31
|
+
* @param priceIn The pool's price for the input asset (from the constant-sum config).
|
|
32
|
+
* @param priceOut The pool's price for the output asset.
|
|
33
|
+
* @param fee The liquidity-provider fee (plus protocol fee) as a fraction.
|
|
34
|
+
* @param roundOutputUp When true, round the output up instead of flooring.
|
|
35
|
+
* @returns The swap details in the shared {@link TSwapOutcome} shape.
|
|
36
|
+
*/
|
|
37
|
+
export declare const getSwapOutput: (inputMetadata: IAssetAmountMetadata, input: bigint, inputReserve: bigint, outputReserve: bigint, priceIn: bigint, priceOut: bigint, fee: TFractionLike, roundOutputUp?: boolean) => TSwapOutcome;
|
|
38
|
+
/**
|
|
39
|
+
* Calculate the minimal input required to receive a given output from a
|
|
40
|
+
* constant-sum pool — the exact inverse of {@link getSwapOutput}.
|
|
41
|
+
*
|
|
42
|
+
* The forward math floors the fee off the input value, which makes the
|
|
43
|
+
* post-fee value `ceil(input·priceIn·(1−fee))`; inverting that ceiling gives
|
|
44
|
+
* the smallest input whose forward swap yields at least `output`.
|
|
45
|
+
*
|
|
46
|
+
* Unlike constant product there is no asymptote, so an output equal to the
|
|
47
|
+
* full output reserve is attainable (the pool can be drained at par).
|
|
48
|
+
*
|
|
49
|
+
* @param inputMetadata Metadata for the supplied (input) asset — used for the fee AssetAmount.
|
|
50
|
+
* @param output The desired amount of the output asset.
|
|
51
|
+
* @param inputReserve The pool's reserve of the input asset.
|
|
52
|
+
* @param outputReserve The pool's reserve of the output asset.
|
|
53
|
+
* @param priceIn The pool's price for the input asset (from the constant-sum config).
|
|
54
|
+
* @param priceOut The pool's price for the output asset.
|
|
55
|
+
* @param fee The liquidity-provider fee (plus protocol fee) as a fraction.
|
|
56
|
+
* @returns The swap details in the shared {@link TSwapOutcome} shape.
|
|
57
|
+
*/
|
|
58
|
+
export declare const getSwapInput: (inputMetadata: IAssetAmountMetadata, output: bigint, inputReserve: bigint, outputReserve: bigint, priceIn: bigint, priceOut: bigint, fee: TFractionLike) => TSwapOutcome;
|
|
59
|
+
/**
|
|
60
|
+
* Calculate the deposit parameters for a 2-asset constant-sum pool via the
|
|
61
|
+
* TARGET-PINNED rule the deployed validator enforces (see
|
|
62
|
+
* {@link calculatePinnedDeposit}): the mint is capped by the scarcest offered
|
|
63
|
+
* asset, both assets must be offered, and anything above the pinned deltas is
|
|
64
|
+
* refunded via aChange/bChange.
|
|
65
|
+
*
|
|
66
|
+
* @param {bigint} a - The amount of token A to deposit.
|
|
67
|
+
* @param {bigint} b - The amount of token B to deposit.
|
|
68
|
+
* @param {bigint} aReserve - The current reserve of token A in the pool.
|
|
69
|
+
* @param {bigint} bReserve - The current reserve of token B in the pool.
|
|
70
|
+
* @param {bigint} totalLp - The total lp tokens for the pool before the deposit.
|
|
71
|
+
* @param {bigint} priceA - The pool's price for token A (from the constant-sum config).
|
|
72
|
+
* @param {bigint} priceB - The pool's price for token B.
|
|
73
|
+
* @throws {Error} If the pool has no value or minted lp.
|
|
74
|
+
* @throws {Error} If both deposit amounts are zero, or either is negative.
|
|
75
|
+
* @throws {Error} If either price is non-positive.
|
|
76
|
+
*/
|
|
77
|
+
export declare const calculateLiquidity: (a: bigint, b: bigint, aReserve: bigint, bReserve: bigint, totalLp: bigint, priceA: bigint, priceB: bigint) => {
|
|
78
|
+
nextTotalLp: bigint;
|
|
79
|
+
generatedLp: bigint;
|
|
80
|
+
shareAfterDeposit: Fraction;
|
|
81
|
+
aChange: bigint;
|
|
82
|
+
bChange: bigint;
|
|
83
|
+
actualDepositedA: bigint;
|
|
84
|
+
actualDepositedB: bigint;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* The N-asset form of {@link calculateLiquidity}, mirroring the v4 contract's
|
|
88
|
+
* `compute_deposit_n` exactly: a deposit of any mix of the pool's assets is
|
|
89
|
+
* valued at the fixed prices against the value of ALL reserves —
|
|
90
|
+
*
|
|
91
|
+
* generatedLp = Σ(amount_i·price_i) · totalLp / Σ(reserve_i·price_i)
|
|
92
|
+
*
|
|
93
|
+
* The three arrays must be aligned to the pool's canonical asset order (the
|
|
94
|
+
* API's `assets`/`quantities`/`prices`). Estimating an N-asset pool's deposit
|
|
95
|
+
* from just two of its reserves overstates the minted LP — the denominator is
|
|
96
|
+
* the whole pool's value — which is exactly the mistake this exists to
|
|
97
|
+
* prevent.
|
|
98
|
+
*/
|
|
99
|
+
/**
|
|
100
|
+
* The target-pinned deposit — what the deployed CS validator (cs_check tag 6)
|
|
101
|
+
* actually accepts, and what the scooper builds. Asymmetric deposits are
|
|
102
|
+
* disallowed on-chain: the fill declares a value delta `t` and every asset's
|
|
103
|
+
* contribution is ceil-pinned to `ceil(r_i·t/V_b)`, with total LP
|
|
104
|
+
* floor-pinned to `floor(lp_b·(V_b+t)/V_b)`. Given what the user offers, the
|
|
105
|
+
* largest fillable t is capped by the SCARCEST asset —
|
|
106
|
+
* `t = min_i floor(offered_i·V_b/r_i)` — and anything above the pinned
|
|
107
|
+
* deltas is returned as surplus. Every pool asset must be offered (> 0) or
|
|
108
|
+
* t is zero and the deposit can never fill.
|
|
109
|
+
*
|
|
110
|
+
* Contrast with `calculateDepositN`, which is the plain value formula:
|
|
111
|
+
* it matches the pin only for exactly proportional offers and OVERSTATES the
|
|
112
|
+
* mint otherwise — using it for `minReceived` makes non-proportional orders
|
|
113
|
+
* unfillable.
|
|
114
|
+
*/
|
|
115
|
+
export declare const calculatePinnedDeposit: (offered: bigint[], reserves: bigint[], prices: bigint[], totalLp: bigint) => {
|
|
116
|
+
targetDeltaV: bigint;
|
|
117
|
+
deltas: bigint[];
|
|
118
|
+
generatedLp: bigint;
|
|
119
|
+
nextTotalLp: bigint;
|
|
120
|
+
shareAfterDeposit: Fraction;
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* The per-asset amounts a pinned deposit needs when the user anchors on one
|
|
124
|
+
* asset's amount: t from the anchor (`floor(anchor·V_b/r_anchor)`), every
|
|
125
|
+
* delta ceil-pinned to it. Drives proportional auto-fill in deposit forms.
|
|
126
|
+
*/
|
|
127
|
+
export declare const pinnedDepositFromAnchor: (anchorIndex: number, anchorAmount: bigint, reserves: bigint[], prices: bigint[]) => bigint[];
|
|
128
|
+
export declare const calculateDepositN: (amounts: bigint[], reserves: bigint[], prices: bigint[], totalLp: bigint) => {
|
|
129
|
+
nextTotalLp: bigint;
|
|
130
|
+
generatedLp: bigint;
|
|
131
|
+
shareAfterDeposit: Fraction;
|
|
132
|
+
};
|
|
133
|
+
//# sourceMappingURL=ConstantSumPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConstantSumPool.d.ts","sourceRoot":"","sources":["../../../src/PoolMath/ConstantSumPool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGpE;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,CAAC,oBAAoB,CAAC,CAAC;IACzC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,QAAQ,CAAC;CACvB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,aAAa,kBACT,oBAAoB,SAC5B,MAAM,gBACC,MAAM,iBACL,MAAM,WACZ,MAAM,YACL,MAAM,OACX,aAAa,kBACF,OAAO,KACtB,YAsDF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,YAAY,kBACR,oBAAoB,UAC3B,MAAM,gBACA,MAAM,iBACL,MAAM,WACZ,MAAM,YACL,MAAM,OACX,aAAa,KACjB,YA2CF,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,MAC1B,MAAM,KACN,MAAM,YACC,MAAM,YACN,MAAM,WACP,MAAM,UACP,MAAM,UACN,MAAM;;;;;;;;CAsBf,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,sBAAsB,YACxB,MAAM,EAAE,YACP,MAAM,EAAE,UACV,MAAM,EAAE,WACP,MAAM,KACd;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,QAAQ,CAAC;CAqC7B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,gBACrB,MAAM,gBACL,MAAM,YACV,MAAM,EAAE,UACV,MAAM,EAAE,KACf,MAAM,EAqBR,CAAC;AAEF,eAAO,MAAM,iBAAiB,YACnB,MAAM,EAAE,YACP,MAAM,EAAE,UACV,MAAM,EAAE,WACP,MAAM;;;;CA6BhB,CAAC"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { AssetAmount, IAssetAmountMetadata } from "@sundaeswap/asset";
|
|
2
|
+
import { Fraction, type TFractionLike } from "@sundaeswap/fraction";
|
|
3
|
+
/**
|
|
4
|
+
* THE V4 STABLESWAP INVARIANT MODULE — NOT THE V3 "STABLESWAPS" CONTRACT.
|
|
5
|
+
*
|
|
6
|
+
* Two different things in this SDK carry the word "stableswap". Keep them
|
|
7
|
+
* apart:
|
|
8
|
+
*
|
|
9
|
+
* - `StableSwapsPool` / `EContractVersion.Stableswaps` is the **v3** stableswap
|
|
10
|
+
* contract. It is a whole contract version with its own datum builder and
|
|
11
|
+
* transaction builder. It stores `D` in the pool datum and has no per-asset
|
|
12
|
+
* rates.
|
|
13
|
+
* - `V4StableswapPool` / `EPoolCurve.V4Stableswap` (this file) is a **v4
|
|
14
|
+
* invariant module**. It is one curve among several a v4 pool can bind, next
|
|
15
|
+
* to constant product, constant sum and concentrated liquidity. It stores no
|
|
16
|
+
* `D` and carries per-asset integer `rates`.
|
|
17
|
+
*
|
|
18
|
+
* The amplification `A` is the ONE thing they share: the same parameter on the
|
|
19
|
+
* same scale, carried by the same `linearAmplificationFactor` field, with each
|
|
20
|
+
* implementation applying its own internal scaling. Everything else is
|
|
21
|
+
* different — do not pass one's reserves, rates or `D` to the other.
|
|
22
|
+
*
|
|
23
|
+
* The curve, on rated and scaled reserves `x = r_a·rate_a·P` and
|
|
24
|
+
* `y = r_b·rate_b·P` with `P = calc_precision = 10^12` and `A` the linear
|
|
25
|
+
* amplification:
|
|
26
|
+
*
|
|
27
|
+
* 4A(x + y) + D = 4AD + D³ / (4xy)
|
|
28
|
+
*
|
|
29
|
+
* `D` is the largest integer that satisfies it. Neither `D` nor a swap output
|
|
30
|
+
* can be computed on-chain, because both need Newton's method. The scooper
|
|
31
|
+
* computes them and the module checks that each supplied integer is the unique
|
|
32
|
+
* one that solves the invariant. This file is the off-chain twin of
|
|
33
|
+
* `lib/modules/ss_math.ak` and `lib/modules/ss_check.ak` in the sundae-v4
|
|
34
|
+
* repository — those are the source of truth; keep this in lockstep with them.
|
|
35
|
+
*/
|
|
36
|
+
/** `ss_math.calc_precision`: the scale applied to reserves before they enter the invariant. */
|
|
37
|
+
export declare const CALC_PRECISION = 1000000000000n;
|
|
38
|
+
/**
|
|
39
|
+
* Holds the calculated outcome of a v4 stableswap swap. Mirrors
|
|
40
|
+
* {@link ConstantProductPool.TSwapOutcome} so it flows through the same generic
|
|
41
|
+
* swap-outcome consumers.
|
|
42
|
+
*
|
|
43
|
+
* `lpFee` is denominated in the **output** asset, not the input asset. The
|
|
44
|
+
* stableswap fee is taken off the gross output (`fee = ceil(gross · feeRate)`),
|
|
45
|
+
* unlike constant product and constant sum which take the fee off the input.
|
|
46
|
+
* The v3 `StableSwapsPool` does the same.
|
|
47
|
+
*/
|
|
48
|
+
export type TSwapOutcome = {
|
|
49
|
+
input: bigint;
|
|
50
|
+
output: bigint;
|
|
51
|
+
lpFee: AssetAmount<IAssetAmountMetadata>;
|
|
52
|
+
nextInputReserve: bigint;
|
|
53
|
+
nextOutputReserve: bigint;
|
|
54
|
+
priceImpact: Fraction;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* `f(D)` from the on-chain `liquidity_invariant`. It is ≤ 0 when `D` is at or
|
|
58
|
+
* below the curve. All arguments are rated and scaled.
|
|
59
|
+
*/
|
|
60
|
+
export declare const invariantF: (x: bigint, y: bigint, amp: bigint, d: bigint) => bigint;
|
|
61
|
+
/**
|
|
62
|
+
* `g(y)` from the on-chain `exchange_invariant`. It is ≥ 0 when the pool keeps
|
|
63
|
+
* enough of the taken asset. `g` is symmetric in `x` and `y`, which is what
|
|
64
|
+
* lets {@link getSwapInput} reuse the same solver in the other direction.
|
|
65
|
+
*/
|
|
66
|
+
export declare const invariantG: (x: bigint, y: bigint, amp: bigint, d: bigint) => bigint;
|
|
67
|
+
/**
|
|
68
|
+
* The sum invariant `D` of a two-asset v4 stableswap pool: the largest integer
|
|
69
|
+
* that satisfies the curve on the rated, scaled reserves. Newton from
|
|
70
|
+
* `D = x + y`, then a ±1 fix-up.
|
|
71
|
+
*
|
|
72
|
+
* `D` carries the `rate · CALC_PRECISION` scale — it is not a token amount.
|
|
73
|
+
*
|
|
74
|
+
* @param amp The pool's `linear_amplification` (`A`), the raw stored integer.
|
|
75
|
+
* @param aReserve The pool's reserve of asset A, in token units.
|
|
76
|
+
* @param bReserve The pool's reserve of asset B, in token units.
|
|
77
|
+
* @param rateA The pool's rate for asset A (from the stableswap config).
|
|
78
|
+
* @param rateB The pool's rate for asset B.
|
|
79
|
+
*/
|
|
80
|
+
export declare const getD: (amp: bigint, aReserve: bigint, bReserve: bigint, rateA?: bigint, rateB?: bigint) => bigint;
|
|
81
|
+
/**
|
|
82
|
+
* The raw swap output: the scaled, pre-fee amount the curve releases when the
|
|
83
|
+
* given reserve becomes `inAfter` and the taken reserve starts at `outBefore`,
|
|
84
|
+
* at the pre-swap `d`. It is the largest such amount the exchange invariant
|
|
85
|
+
* admits — one unit more leaves the pool below the curve — and it is at or
|
|
86
|
+
* below the exact real-valued output, so it never over-quotes.
|
|
87
|
+
*
|
|
88
|
+
* The result carries the `rate · CALC_PRECISION` scale. Divide by
|
|
89
|
+
* `rateOut · CALC_PRECISION` to get the gross output in token units.
|
|
90
|
+
*
|
|
91
|
+
* @param amp The pool's `linear_amplification` (`A`), the raw stored integer.
|
|
92
|
+
* @param d The pre-swap sum invariant, from {@link getD}.
|
|
93
|
+
* @param inAfter The given asset's reserve after the input arrives, in token units.
|
|
94
|
+
* @param outBefore The taken asset's reserve before the swap, in token units.
|
|
95
|
+
* @param rateIn The pool's rate for the given asset.
|
|
96
|
+
* @param rateOut The pool's rate for the taken asset.
|
|
97
|
+
*/
|
|
98
|
+
export declare const getRawSwap: (amp: bigint, d: bigint, inAfter: bigint, outBefore: bigint, rateIn?: bigint, rateOut?: bigint) => bigint;
|
|
99
|
+
/**
|
|
100
|
+
* The pool's marginal price as raw units of asset A per raw unit of asset B.
|
|
101
|
+
* Use it where a constant-product pool would use the reserve ratio: for a
|
|
102
|
+
* stableswap pool the reserve ratio is not the price, because the curve holds
|
|
103
|
+
* the price near par across a wide band of ratios.
|
|
104
|
+
*
|
|
105
|
+
* The result is in raw (undecimalized) units. Adjust for the two assets'
|
|
106
|
+
* decimals before display.
|
|
107
|
+
*/
|
|
108
|
+
export declare const getPrice: (amp: bigint, aReserve: bigint, bReserve: bigint, rateA?: bigint, rateB?: bigint) => Fraction;
|
|
109
|
+
/**
|
|
110
|
+
* Calculate the swap outcome for a v4 stableswap pool.
|
|
111
|
+
*
|
|
112
|
+
* The sequence the chain enforces (`ss_check.ak`, tag 3):
|
|
113
|
+
*
|
|
114
|
+
* 1. `D` is derived from the pre-swap reserves at the pool's rates.
|
|
115
|
+
* 2. `raw` is the LARGEST scaled output the exchange invariant admits at that
|
|
116
|
+
* `D`, with the input already added to the given reserve. The solver pins
|
|
117
|
+
* the pool's remaining taken reserve `y` to the SMALLEST integer that still
|
|
118
|
+
* satisfies the invariant, and `raw = outBefore·rateOut·P − y`, so the two
|
|
119
|
+
* statements are the same one: least reserve kept, most output released.
|
|
120
|
+
* 3. `gross = floor(raw / (rateOut · CALC_PRECISION))` is the output in token units.
|
|
121
|
+
* 4. `fee = ceil(gross · feeRate)` stays in the pool.
|
|
122
|
+
* 5. The trader receives `gross − fee`.
|
|
123
|
+
*
|
|
124
|
+
* Every rounding step favours the pool, never the trader: `y` is a ceiling on
|
|
125
|
+
* the exact reserve the curve requires, `gross` floors to whole tokens, and the
|
|
126
|
+
* fee ceilings. A trader is never quoted more than the chain will pay.
|
|
127
|
+
*
|
|
128
|
+
* @param outputMetadata Metadata for the **taken** asset. The fee is denominated in it.
|
|
129
|
+
* @param input The amount of the given asset being swapped.
|
|
130
|
+
* @param inputReserve The pool's reserve of the given asset.
|
|
131
|
+
* @param outputReserve The pool's reserve of the taken asset.
|
|
132
|
+
* @param rateIn The pool's rate for the given asset (from the stableswap config).
|
|
133
|
+
* @param rateOut The pool's rate for the taken asset.
|
|
134
|
+
* @param amp The pool's `linear_amplification` (`A`), the raw stored integer.
|
|
135
|
+
* @param fee The swap fee rate, applied to the gross output.
|
|
136
|
+
* @returns The swap details in the shared {@link TSwapOutcome} shape.
|
|
137
|
+
*/
|
|
138
|
+
export declare const getSwapOutput: (outputMetadata: IAssetAmountMetadata, input: bigint, inputReserve: bigint, outputReserve: bigint, rateIn: bigint, rateOut: bigint, amp: bigint, fee: TFractionLike) => TSwapOutcome;
|
|
139
|
+
/**
|
|
140
|
+
* Calculate the minimal input that buys a given output — the inverse of
|
|
141
|
+
* {@link getSwapOutput}.
|
|
142
|
+
*
|
|
143
|
+
* The steps:
|
|
144
|
+
*
|
|
145
|
+
* 1. Invert the fee: the smallest gross output that nets `output` after
|
|
146
|
+
* `ceil(gross · feeRate)` is `ceil(output · feeDen / (feeDen − feeNum))`.
|
|
147
|
+
* 2. Turn that gross into the scaled reserve the pool may keep of the taken
|
|
148
|
+
* asset.
|
|
149
|
+
* 3. Solve the exchange invariant in the other direction for the given
|
|
150
|
+
* reserve that supports it. `g` is symmetric, so this is the same solver.
|
|
151
|
+
* 4. Convert to token units and walk down to the minimum, which absorbs the
|
|
152
|
+
* integer rounding of step 3.
|
|
153
|
+
*
|
|
154
|
+
* @param outputMetadata Metadata for the **taken** asset. The fee is denominated in it.
|
|
155
|
+
* @param output The wanted amount of the taken asset.
|
|
156
|
+
* @param inputReserve The pool's reserve of the given asset.
|
|
157
|
+
* @param outputReserve The pool's reserve of the taken asset.
|
|
158
|
+
* @param rateIn The pool's rate for the given asset (from the stableswap config).
|
|
159
|
+
* @param rateOut The pool's rate for the taken asset.
|
|
160
|
+
* @param amp The pool's `linear_amplification` (`A`), the raw stored integer.
|
|
161
|
+
* @param fee The swap fee rate, applied to the gross output.
|
|
162
|
+
* @returns The swap details in the shared {@link TSwapOutcome} shape.
|
|
163
|
+
*/
|
|
164
|
+
export declare const getSwapInput: (outputMetadata: IAssetAmountMetadata, output: bigint, inputReserve: bigint, outputReserve: bigint, rateIn: bigint, rateOut: bigint, amp: bigint, fee: TFractionLike) => TSwapOutcome;
|
|
165
|
+
/**
|
|
166
|
+
* The deposit target a holder of `offered` can cover, and everything pinned to
|
|
167
|
+
* it. This is the target-pinned rule the v4 module enforces (`ss_check.ak`,
|
|
168
|
+
* tag 6), and it is the same shape constant sum uses, stated on `D` instead of
|
|
169
|
+
* on the value sum `V`:
|
|
170
|
+
*
|
|
171
|
+
* - the fill declares a `D` delta `t`;
|
|
172
|
+
* - every reserve moves by `ceil(r_i · t / D_before)`;
|
|
173
|
+
* - `total_lp` becomes `floor(lp_before · (D_before + t) / D_before)`.
|
|
174
|
+
*
|
|
175
|
+
* The largest `t` a holder can cover is capped by the scarcest offered asset,
|
|
176
|
+
* `t = min_i floor(offered_i · D_before / r_i)`. Anything above the pinned
|
|
177
|
+
* deltas is refunded. Every pool asset must be offered, or `t` is zero and the
|
|
178
|
+
* deposit can never fill.
|
|
179
|
+
*
|
|
180
|
+
* The rates do not enter the deltas: a proportional move is proportional in
|
|
181
|
+
* any units. They enter only through `D`.
|
|
182
|
+
*/
|
|
183
|
+
export declare const calculatePinnedDeposit: (offered: bigint[], reserves: bigint[], totalLp: bigint, d: bigint) => {
|
|
184
|
+
targetDeltaD: bigint;
|
|
185
|
+
deltas: bigint[];
|
|
186
|
+
generatedLp: bigint;
|
|
187
|
+
nextTotalLp: bigint;
|
|
188
|
+
shareAfterDeposit: Fraction;
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* Calculate the deposit parameters for a two-asset v4 stableswap pool through
|
|
192
|
+
* the target-pinned rule (see {@link calculatePinnedDeposit}). Surplus above
|
|
193
|
+
* the pinned deltas comes back as `aChange` / `bChange`, the way the scoop
|
|
194
|
+
* refunds it on-chain.
|
|
195
|
+
*
|
|
196
|
+
* @param a The amount of token A to deposit.
|
|
197
|
+
* @param b The amount of token B to deposit.
|
|
198
|
+
* @param aReserve The pool's reserve of token A.
|
|
199
|
+
* @param bReserve The pool's reserve of token B.
|
|
200
|
+
* @param totalLp The pool's total LP supply before the deposit.
|
|
201
|
+
* @param rateA The pool's rate for token A (from the stableswap config).
|
|
202
|
+
* @param rateB The pool's rate for token B.
|
|
203
|
+
* @param amp The pool's `linear_amplification` (`A`), the raw stored integer.
|
|
204
|
+
*/
|
|
205
|
+
export declare const calculateLiquidity: (a: bigint, b: bigint, aReserve: bigint, bReserve: bigint, totalLp: bigint, rateA: bigint, rateB: bigint, amp: bigint) => {
|
|
206
|
+
nextTotalLp: bigint;
|
|
207
|
+
generatedLp: bigint;
|
|
208
|
+
shareAfterDeposit: Fraction;
|
|
209
|
+
aChange: bigint;
|
|
210
|
+
bChange: bigint;
|
|
211
|
+
actualDepositedA: bigint;
|
|
212
|
+
actualDepositedB: bigint;
|
|
213
|
+
};
|
|
214
|
+
/**
|
|
215
|
+
* The per-asset amounts a pinned deposit needs when the user anchors on one
|
|
216
|
+
* asset's amount: `t` from the anchor (`floor(anchor · D / r_anchor)`), every
|
|
217
|
+
* other delta ceil-pinned to it. Drives proportional auto-fill in deposit
|
|
218
|
+
* forms.
|
|
219
|
+
*/
|
|
220
|
+
export declare const pinnedDepositFromAnchor: (anchorIndex: number, anchorAmount: bigint, reserves: bigint[], d: bigint) => bigint[];
|
|
221
|
+
//# sourceMappingURL=V4StableswapPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"V4StableswapPool.d.ts","sourceRoot":"","sources":["../../../src/PoolMath/V4StableswapPool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,+FAA+F;AAC/F,eAAO,MAAM,cAAc,iBAAqB,CAAC;AAQjD;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,CAAC,oBAAoB,CAAC,CAAC;IACzC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,QAAQ,CAAC;CACvB,CAAC;AAuBF;;;GAGG;AACH,eAAO,MAAM,UAAU,MAClB,MAAM,KACN,MAAM,OACJ,MAAM,KACR,MAAM,KACR,MAGF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,MAClB,MAAM,KACN,MAAM,OACJ,MAAM,KACR,MAAM,KACR,MAGF,CAAC;AAYF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,IAAI,QACV,MAAM,YACD,MAAM,YACN,MAAM,qCAGf,MAiCF,CAAC;AA+CF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,UAAU,QAChB,MAAM,KACR,MAAM,WACA,MAAM,aACJ,MAAM,wCAGhB,MAQF,CAAC;AA6BF;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ,QACd,MAAM,YACD,MAAM,YACN,MAAM,qCAGf,QAQF,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,aAAa,mBACR,oBAAoB,SAC7B,MAAM,gBACC,MAAM,iBACL,MAAM,UACb,MAAM,WACL,MAAM,OACV,MAAM,OACN,aAAa,KACjB,YA6CF,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,YAAY,mBACP,oBAAoB,UAC5B,MAAM,gBACA,MAAM,iBACL,MAAM,UACb,MAAM,WACL,MAAM,OACV,MAAM,OACN,aAAa,KACjB,YAuEF,CAAC;AAIF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,sBAAsB,YACxB,MAAM,EAAE,YACP,MAAM,EAAE,WACT,MAAM,KACZ,MAAM,KACR;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,QAAQ,CAAC;CAgC7B,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kBAAkB,MAC1B,MAAM,KACN,MAAM,YACC,MAAM,YACN,MAAM,WACP,MAAM,SACR,MAAM,SACN,MAAM,OACR,MAAM;;;;;;;;CAiBZ,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,gBACrB,MAAM,gBACL,MAAM,YACV,MAAM,EAAE,KACf,MAAM,KACR,MAAM,EAYR,CAAC"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
export * as ConcentratedLiquidityPool from "./ConcentratedLiquidityPool.js";
|
|
1
2
|
export * as ConstantProductPool from "./ConstantProductPool.js";
|
|
3
|
+
export * as ConstantSumPool from "./ConstantSumPool.js";
|
|
2
4
|
export * as StableSwapsPool from "./StableSwapsPool.js";
|
|
5
|
+
export * as V4StableswapPool from "./V4StableswapPool.js";
|
|
3
6
|
export * as SharedPoolMath from "./SharedPoolMath.js";
|
|
4
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/PoolMath/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,mBAAmB,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/PoolMath/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,yBAAyB,MAAM,gCAAgC,CAAC;AAC5E,OAAO,KAAK,mBAAmB,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC"}
|