@exponent-labs/market-three-math 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +197 -0
  3. package/build/addLiquidity.d.ts +67 -0
  4. package/build/addLiquidity.js +269 -0
  5. package/build/addLiquidity.js.map +1 -0
  6. package/build/bisect.d.ts +1 -0
  7. package/build/bisect.js +62 -0
  8. package/build/bisect.js.map +1 -0
  9. package/build/index.d.ts +24 -0
  10. package/build/index.js +76 -0
  11. package/build/index.js.map +1 -0
  12. package/build/liquidityHistogram.d.ts +50 -0
  13. package/build/liquidityHistogram.js +162 -0
  14. package/build/liquidityHistogram.js.map +1 -0
  15. package/build/quote.d.ts +18 -0
  16. package/build/quote.js +106 -0
  17. package/build/quote.js.map +1 -0
  18. package/build/swap-v2.d.ts +20 -0
  19. package/build/swap-v2.js +261 -0
  20. package/build/swap-v2.js.map +1 -0
  21. package/build/swap.d.ts +15 -0
  22. package/build/swap.js +249 -0
  23. package/build/swap.js.map +1 -0
  24. package/build/swapLegacy.d.ts +16 -0
  25. package/build/swapLegacy.js +229 -0
  26. package/build/swapLegacy.js.map +1 -0
  27. package/build/swapV2.d.ts +11 -0
  28. package/build/swapV2.js +406 -0
  29. package/build/swapV2.js.map +1 -0
  30. package/build/types.d.ts +73 -0
  31. package/build/types.js +9 -0
  32. package/build/types.js.map +1 -0
  33. package/build/utils.d.ts +119 -0
  34. package/build/utils.js +219 -0
  35. package/build/utils.js.map +1 -0
  36. package/build/utilsV2.d.ts +88 -0
  37. package/build/utilsV2.js +180 -0
  38. package/build/utilsV2.js.map +1 -0
  39. package/build/withdrawLiquidity.d.ts +8 -0
  40. package/build/withdrawLiquidity.js +174 -0
  41. package/build/withdrawLiquidity.js.map +1 -0
  42. package/build/ytTrades.d.ts +106 -0
  43. package/build/ytTrades.js +292 -0
  44. package/build/ytTrades.js.map +1 -0
  45. package/build/ytTradesLegacy.d.ts +106 -0
  46. package/build/ytTradesLegacy.js +292 -0
  47. package/build/ytTradesLegacy.js.map +1 -0
  48. package/examples/.env.example +1 -0
  49. package/examples/test-histogram-simple.ts +172 -0
  50. package/examples/test-histogram.ts +112 -0
  51. package/package.json +26 -0
  52. package/src/addLiquidity.ts +384 -0
  53. package/src/bisect.ts +72 -0
  54. package/src/index.ts +74 -0
  55. package/src/liquidityHistogram.ts +192 -0
  56. package/src/quote.ts +128 -0
  57. package/src/swap.ts +299 -0
  58. package/src/swapLegacy.ts +272 -0
  59. package/src/types.ts +80 -0
  60. package/src/utils.ts +235 -0
  61. package/src/withdrawLiquidity.ts +240 -0
  62. package/src/ytTrades.ts +419 -0
  63. package/tsconfig.json +17 -0
@@ -0,0 +1,292 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.simulateSellYt = exports.simulateBuyYtWithSyIn = exports.simulateBuyYt = void 0;
4
+ /**
5
+ * YT (Yield Token) trade simulations
6
+ *
7
+ * YT trades are multi-step operations that involve PT trades:
8
+ * - Buy YT: Strip SY → PT+YT, then sell PT back to pool
9
+ * - Sell YT: Merge PT+YT → SY, then buy PT from pool to repay
10
+ */
11
+ const bisect_1 = require("./bisect");
12
+ const swap_1 = require("./swap");
13
+ const types_1 = require("./types");
14
+ /**
15
+ * Helper function to convert PY to SY
16
+ * @param syExchangeRate - The SY exchange rate
17
+ * @param pyAmount - The PY (PT or YT) amount
18
+ * @returns The equivalent SY amount
19
+ */
20
+ function pyToSy(syExchangeRate, pyAmount) {
21
+ if (syExchangeRate <= 0)
22
+ return 0;
23
+ return Math.floor(pyAmount / syExchangeRate);
24
+ }
25
+ /**
26
+ * Helper function to convert SY to PY
27
+ * @param syExchangeRate - The SY exchange rate
28
+ * @param syAmount - The SY amount
29
+ * @returns The equivalent PY amount
30
+ */
31
+ function syToPy(syExchangeRate, syAmount) {
32
+ return Math.floor(syAmount * syExchangeRate);
33
+ }
34
+ /**
35
+ * Simulates buying YT tokens
36
+ *
37
+ * Process:
38
+ * 1. Calculate how much SY to strip to get desired YT
39
+ * 2. Strip SY → PT + YT (PT amount ≈ YT amount)
40
+ * 3. Sell PT to the pool (PtToSy direction)
41
+ * 4. Net cost = SY stripped - SY received from PT sale
42
+ *
43
+ * @param marketState - Current market state
44
+ * @param args - Simulation arguments
45
+ * @returns Simulation result with net SY cost
46
+ */
47
+ function simulateBuyYt(marketState, args) {
48
+ const { ytOut, syExchangeRate, priceSpotLimit } = args;
49
+ // Calculate how much SY needs to be stripped to get the desired YT
50
+ // Add 1 to counter-act the flooring function when converting from PY to SY
51
+ const syToStrip = pyToSy(syExchangeRate, ytOut) + 1;
52
+ // Stripping gives approximately equal amounts of PT and YT
53
+ const ptFromStrip = ytOut;
54
+ // Simulate selling the PT to get SY back
55
+ // Note: We use ytOut as the amount because PT out = YT out from the strip
56
+ const swapResult = (0, swap_1.simulateSwap)(marketState, {
57
+ direction: types_1.SwapDirection.PtToSy,
58
+ amountIn: ytOut,
59
+ priceSpotLimit,
60
+ syExchangeRate,
61
+ isCurrentFlashSwap: true,
62
+ });
63
+ const syFromPtSale = swapResult.amountOut;
64
+ // Net cost is the difference between what was stripped and what was received
65
+ const netSyCost = syToStrip - syFromPtSale;
66
+ return {
67
+ ytOut,
68
+ netSyCost,
69
+ syToStrip,
70
+ ptFromStrip,
71
+ syFromPtSale,
72
+ lpFee: swapResult.lpFeeChargedOutToken,
73
+ protocolFee: swapResult.protocolFeeChargedOutToken,
74
+ finalSpotPrice: swapResult.finalSpotPrice,
75
+ };
76
+ }
77
+ exports.simulateBuyYt = simulateBuyYt;
78
+ /**
79
+ * Simulates buying YT tokens given a SY input amount
80
+ *
81
+ * Process:
82
+ * 1. Strip syIn → PT + YT
83
+ * 2. Sell PT → get SY back (with price impact)
84
+ * 3. Strip SY again → more PT + YT
85
+ * 4. Repeat until convergence
86
+ * Total YT = YT₁ + YT₂ + YT₃ + ...
87
+ *
88
+ * Uses bisection search to find ytOut such that netSyCost = syIn
89
+ *
90
+ * @param marketState - Current market state
91
+ * @param args - Simulation arguments
92
+ * @returns Simulation result with calculated YT output
93
+ */
94
+ function simulateBuyYtWithSyIn(marketState, args) {
95
+ const { syIn, syExchangeRate, priceSpotLimit } = args;
96
+ // Lower bound: Start very low since PT recycling allows buying much more YT than naive calculation
97
+ // The actual minimum depends on PT price (how much SY we get back from selling PT)
98
+ // If PT price is high (close to 1), we get most SY back, so we can buy much more YT
99
+ // Example: With 1000 SY and PT price 0.9:
100
+ // - To get 5000 YT, strip 5000 SY → 5000 PT + 5000 YT
101
+ // - Sell 5000 PT at 0.9 → 4500 SY back
102
+ // - Net cost: 5000 - 4500 = 500 SY (way less than 1000!)
103
+ const minPossibleYt = 1;
104
+ // Better initial upper bound estimate based on market liquidity
105
+ // Maximum possible YT is constrained by available PT liquidity in the market
106
+ const marketPtLiquidity = Number(marketState.financials.ptBalance);
107
+ const marketSyLiquidity = Number(marketState.financials.syBalance);
108
+ // Conservative estimate: we can't buy more YT than there's PT in the market
109
+ // High multiplier needed because PT recycling amplifies buying power dramatically
110
+ // Formula: ytOut ≈ syIn / (1 - ptPrice)
111
+ // Examples: PT@0.99 → 100x, PT@0.95 → 20x, PT@0.90 → 10x, PT@0.80 → 5x
112
+ const liquidityBasedMax = Math.min(marketPtLiquidity * 0.9, // 90% of PT liquidity to be safe
113
+ syToPy(syExchangeRate, syIn) * 100);
114
+ // Start with a reasonable initial guess (10x covers most realistic scenarios)
115
+ let maxPossibleYt = Math.min(syToPy(syExchangeRate, syIn) * 10, liquidityBasedMax);
116
+ let foundUpperBound = false;
117
+ let lastValidCost = 0;
118
+ // Use exponential search with better growth rate
119
+ for (let attempt = 0; attempt < 12; attempt++) {
120
+ try {
121
+ const syToStrip = pyToSy(syExchangeRate, maxPossibleYt) + 1;
122
+ const swapResult = (0, swap_1.simulateSwap)(marketState, {
123
+ direction: types_1.SwapDirection.PtToSy,
124
+ amountIn: maxPossibleYt,
125
+ priceSpotLimit,
126
+ syExchangeRate,
127
+ isCurrentFlashSwap: true,
128
+ });
129
+ const syFromPtSale = swapResult.amountOut;
130
+ const netSyCost = syToStrip - syFromPtSale;
131
+ // If this costs more than syIn, we found our upper bound
132
+ if (netSyCost > syIn) {
133
+ foundUpperBound = true;
134
+ break;
135
+ }
136
+ lastValidCost = netSyCost;
137
+ // Use adaptive growth rate based on how far we are from target
138
+ const costRatio = syIn / Math.max(netSyCost, 1);
139
+ const growthFactor = attempt < 3 ? 2.0 : Math.min(1.5, 1 + costRatio * 0.3);
140
+ maxPossibleYt *= growthFactor;
141
+ // Don't exceed liquidity constraints
142
+ if (maxPossibleYt > liquidityBasedMax) {
143
+ maxPossibleYt = liquidityBasedMax;
144
+ foundUpperBound = true;
145
+ break;
146
+ }
147
+ }
148
+ catch (error) {
149
+ // If simulation fails, we've exceeded market capacity
150
+ // Use last valid value with small buffer, ensuring it's > minPossibleYt
151
+ if (lastValidCost > 0) {
152
+ // Interpolate to find better upper bound
153
+ const estimatedMax = maxPossibleYt * 0.7 * (syIn / lastValidCost);
154
+ maxPossibleYt = Math.max(estimatedMax, minPossibleYt * 1.2);
155
+ }
156
+ else {
157
+ // No valid cost yet, use a conservative upper bound
158
+ maxPossibleYt = Math.max(maxPossibleYt * 0.8, minPossibleYt * 1.5);
159
+ }
160
+ foundUpperBound = true;
161
+ break;
162
+ }
163
+ }
164
+ if (!foundUpperBound) {
165
+ throw new Error(`Could not find upper bound for YT amount. Market may have unusual price dynamics.`);
166
+ }
167
+ // Final safety check: ensure maxPossibleYt > minPossibleYt
168
+ if (maxPossibleYt <= minPossibleYt) {
169
+ maxPossibleYt = minPossibleYt * 2;
170
+ }
171
+ // Use bisection search to find the ytOut that results in netSyCost = syIn
172
+ // Adaptive epsilon based on input size for better precision scaling
173
+ const adaptiveEpsilon = Math.max(0.01, syIn * 0.0001);
174
+ // Reduce max iterations since we have better bounds
175
+ const maxIterations = 10000;
176
+ // Debug info for bounds validation
177
+ if (maxPossibleYt <= minPossibleYt) {
178
+ throw new Error(`Invalid bisection bounds for buy YT. ` +
179
+ `Min: ${minPossibleYt}, Max: ${maxPossibleYt}, ` +
180
+ `SyIn: ${syIn}, SyExchangeRate: ${syExchangeRate}, ` +
181
+ `MarketPtBalance: ${marketPtLiquidity}, MarketSyBalance: ${marketSyLiquidity}`);
182
+ }
183
+ const ytOut = (0, bisect_1.bisectSearch2)((ytGuess) => {
184
+ // Calculate the cost for this ytGuess
185
+ const syToStrip = pyToSy(syExchangeRate, ytGuess) + 1;
186
+ const swapResult = (0, swap_1.simulateSwap)(marketState, {
187
+ direction: types_1.SwapDirection.PtToSy,
188
+ amountIn: ytGuess,
189
+ priceSpotLimit,
190
+ syExchangeRate,
191
+ isCurrentFlashSwap: true,
192
+ });
193
+ const syFromPtSale = swapResult.amountOut;
194
+ const netSyCost = syToStrip - syFromPtSale;
195
+ // Return the difference between actual cost and target syIn
196
+ return netSyCost - syIn;
197
+ }, minPossibleYt, maxPossibleYt, adaptiveEpsilon, maxIterations);
198
+ if (ytOut === null) {
199
+ throw new Error(`Failed to converge on correct YT amount. ` +
200
+ `Search range: [${minPossibleYt}, ${maxPossibleYt}], ` +
201
+ `Epsilon: ${adaptiveEpsilon}`);
202
+ }
203
+ // Now calculate the full result with the found ytOut
204
+ return simulateBuyYt(marketState, {
205
+ ytOut,
206
+ syExchangeRate,
207
+ priceSpotLimit,
208
+ });
209
+ }
210
+ exports.simulateBuyYtWithSyIn = simulateBuyYtWithSyIn;
211
+ /**
212
+ * Simulates selling YT tokens
213
+ *
214
+ * Process:
215
+ * 1. Merge PT + YT → SY (receive SY from the merge)
216
+ * 2. Buy PT from the pool to repay the borrowed PT (SyToPt direction)
217
+ * 3. Net received = SY from merge - SY spent on PT
218
+ *
219
+ * Note: The market must have at least 2x the YT amount in PT liquidity
220
+ * because the trader borrows PT, which is then bought back.
221
+ *
222
+ * @param marketState - Current market state
223
+ * @param args - Simulation arguments
224
+ * @returns Simulation result with net SY received
225
+ */
226
+ function simulateSellYt(marketState, args) {
227
+ const { ytIn, syExchangeRate, priceSpotLimit } = args;
228
+ // Check if there's sufficient PT liquidity
229
+ // The market needs at least 2x the YT amount in PT
230
+ if (marketState.financials.ptBalance < ytIn * 2) {
231
+ throw new Error(`Insufficient PT liquidity in the market. Required: ${ytIn * 2}, Available: ${marketState.financials.ptBalance}`);
232
+ }
233
+ // Merging PT + YT gives back the original SY
234
+ // The amount of PT needed equals ytIn (1:1 ratio)
235
+ const syFromMerge = pyToSy(syExchangeRate, ytIn);
236
+ const ptNeeded = ytIn;
237
+ const upperBoundSwap = (0, swap_1.simulateSwap)(marketState, {
238
+ direction: types_1.SwapDirection.SyToPt,
239
+ amountIn: syFromMerge,
240
+ priceSpotLimit,
241
+ syExchangeRate,
242
+ isCurrentFlashSwap: true,
243
+ });
244
+ // Check that we can buy enough PT from CLMM
245
+ if (upperBoundSwap.amountOut < ptNeeded) {
246
+ throw new Error(`Cannot buy enough PT with available SY. Need ${ytIn} PT but can only afford ${upperBoundSwap.amountOut} PT`);
247
+ }
248
+ // Better initial bounds for bisection
249
+ // We know the upper bound from the check above, and we can estimate a better lower bound
250
+ // based on the current price
251
+ const estimatedLowerBound = Math.min(syFromMerge * 0.5, syFromMerge * 0.9); // Start from 50% of max, but not too close to upper
252
+ // Adaptive epsilon based on PT needed
253
+ const adaptiveEpsilon = Math.max(0.01, ptNeeded * 0.0001);
254
+ // Safety check: ensure lower bound is less than upper bound
255
+ const safeLowerBound = Math.min(estimatedLowerBound, syFromMerge * 0.95);
256
+ const safeUpperBound = syFromMerge;
257
+ if (safeLowerBound >= safeUpperBound) {
258
+ throw new Error(`Invalid bisection bounds for sell YT. Lower: ${safeLowerBound}, Upper: ${safeUpperBound}`);
259
+ }
260
+ const syToSpend = (0, bisect_1.bisectSearch2)((syGuess) => {
261
+ const swapResult = (0, swap_1.simulateSwap)(marketState, {
262
+ direction: types_1.SwapDirection.SyToPt,
263
+ amountIn: syGuess,
264
+ priceSpotLimit,
265
+ syExchangeRate,
266
+ isCurrentFlashSwap: true,
267
+ });
268
+ return swapResult.amountOut - ptNeeded;
269
+ }, safeLowerBound, safeUpperBound, adaptiveEpsilon, 100);
270
+ if (syToSpend === null) {
271
+ throw new Error("Failed to converge on correct SY amount using bisection search");
272
+ }
273
+ const swapResult = (0, swap_1.simulateSwap)(marketState, {
274
+ direction: types_1.SwapDirection.SyToPt,
275
+ amountIn: syToSpend,
276
+ priceSpotLimit,
277
+ syExchangeRate,
278
+ isCurrentFlashSwap: true,
279
+ });
280
+ const netSyReceived = syFromMerge - swapResult.amountInConsumed;
281
+ return {
282
+ ytIn,
283
+ netSyReceived,
284
+ syFromMerge,
285
+ sySpentOnPt: swapResult.amountInConsumed,
286
+ lpFee: swapResult.lpFeeChargedOutToken,
287
+ protocolFee: swapResult.protocolFeeChargedOutToken,
288
+ finalSpotPrice: swapResult.finalSpotPrice,
289
+ };
290
+ }
291
+ exports.simulateSellYt = simulateSellYt;
292
+ //# sourceMappingURL=ytTrades.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ytTrades.js","sourceRoot":"","sources":["../src/ytTrades.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ import { MarketThreeState } from "./types";
2
+ export interface BuyYtSimulationArgs {
3
+ /** Amount of YT desired to buy */
4
+ ytOut: number;
5
+ /** SY exchange rate */
6
+ syExchangeRate: number;
7
+ /** Optional spot price limit (anti-sandwich) */
8
+ priceSpotLimit?: number;
9
+ }
10
+ export interface BuyYtSimulationResult {
11
+ /** Amount of YT received */
12
+ ytOut: number;
13
+ /** Net SY cost to the trader */
14
+ netSyCost: number;
15
+ /** Amount of SY that needs to be stripped */
16
+ syToStrip: number;
17
+ /** Amount of PT received from stripping */
18
+ ptFromStrip: number;
19
+ /** Amount of SY received from selling PT */
20
+ syFromPtSale: number;
21
+ /** LP fee charged */
22
+ lpFee: number;
23
+ /** Protocol fee charged */
24
+ protocolFee: number;
25
+ /** Final spot price after the trade */
26
+ finalSpotPrice: number;
27
+ }
28
+ /**
29
+ * Simulates buying YT tokens
30
+ *
31
+ * Process:
32
+ * 1. Calculate how much SY to strip to get desired YT
33
+ * 2. Strip SY → PT + YT (PT amount ≈ YT amount)
34
+ * 3. Sell PT to the pool (PtToSy direction)
35
+ * 4. Net cost = SY stripped - SY received from PT sale
36
+ *
37
+ * @param marketState - Current market state
38
+ * @param args - Simulation arguments
39
+ * @returns Simulation result with net SY cost
40
+ */
41
+ export declare function simulateBuyYt(marketState: MarketThreeState, args: BuyYtSimulationArgs): BuyYtSimulationResult;
42
+ export interface BuyYtWithSyInSimulationArgs {
43
+ /** Amount of SY to spend */
44
+ syIn: number;
45
+ /** SY exchange rate */
46
+ syExchangeRate: number;
47
+ /** Optional spot price limit (anti-sandwich) */
48
+ priceSpotLimit?: number;
49
+ }
50
+ /**
51
+ * Simulates buying YT tokens given a SY input amount
52
+ *
53
+ * Process:
54
+ * 1. Strip syIn → PT + YT
55
+ * 2. Sell PT → get SY back (with price impact)
56
+ * 3. Strip SY again → more PT + YT
57
+ * 4. Repeat until convergence
58
+ * Total YT = YT₁ + YT₂ + YT₃ + ...
59
+ *
60
+ * Uses bisection search to find ytOut such that netSyCost = syIn
61
+ *
62
+ * @param marketState - Current market state
63
+ * @param args - Simulation arguments
64
+ * @returns Simulation result with calculated YT output
65
+ */
66
+ export declare function simulateBuyYtWithSyIn(marketState: MarketThreeState, args: BuyYtWithSyInSimulationArgs): BuyYtSimulationResult;
67
+ export interface SellYtSimulationArgs {
68
+ /** Amount of YT to sell */
69
+ ytIn: number;
70
+ /** SY exchange rate */
71
+ syExchangeRate: number;
72
+ /** Optional spot price limit (anti-sandwich) */
73
+ priceSpotLimit?: number;
74
+ }
75
+ export interface SellYtSimulationResult {
76
+ /** Amount of YT sold */
77
+ ytIn: number;
78
+ /** Net SY received by the trader */
79
+ netSyReceived: number;
80
+ /** Amount of SY received from merging PT + YT */
81
+ syFromMerge: number;
82
+ /** Amount of SY spent buying PT back */
83
+ sySpentOnPt: number;
84
+ /** LP fee charged */
85
+ lpFee: number;
86
+ /** Protocol fee charged */
87
+ protocolFee: number;
88
+ /** Final spot price after the trade */
89
+ finalSpotPrice: number;
90
+ }
91
+ /**
92
+ * Simulates selling YT tokens
93
+ *
94
+ * Process:
95
+ * 1. Merge PT + YT → SY (receive SY from the merge)
96
+ * 2. Buy PT from the pool to repay the borrowed PT (SyToPt direction)
97
+ * 3. Net received = SY from merge - SY spent on PT
98
+ *
99
+ * Note: The market must have at least 2x the YT amount in PT liquidity
100
+ * because the trader borrows PT, which is then bought back.
101
+ *
102
+ * @param marketState - Current market state
103
+ * @param args - Simulation arguments
104
+ * @returns Simulation result with net SY received
105
+ */
106
+ export declare function simulateSellYt(marketState: MarketThreeState, args: SellYtSimulationArgs): SellYtSimulationResult;