@exponent-labs/market-three-math 0.1.8 → 0.9.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/build/addLiquidity.d.ts +65 -4
- package/build/addLiquidity.js +757 -30
- package/build/addLiquidity.js.map +1 -1
- package/build/bisect.d.ts +11 -0
- package/build/bisect.js +21 -10
- package/build/bisect.js.map +1 -1
- package/build/index.d.ts +5 -4
- package/build/index.js +14 -7
- package/build/index.js.map +1 -1
- package/build/liquidityHistogram.d.ts +6 -1
- package/build/liquidityHistogram.js +55 -9
- package/build/liquidityHistogram.js.map +1 -1
- package/build/quote.d.ts +1 -1
- package/build/quote.js +68 -82
- package/build/quote.js.map +1 -1
- package/build/swap.js +35 -16
- package/build/swap.js.map +1 -1
- package/build/swapV2.d.ts +6 -1
- package/build/swapV2.js +394 -51
- package/build/swapV2.js.map +1 -1
- package/build/types.d.ts +51 -0
- package/build/utils.d.ts +8 -2
- package/build/utils.js +23 -5
- package/build/utils.js.map +1 -1
- package/build/utilsV2.d.ts +9 -0
- package/build/utilsV2.js +127 -5
- package/build/utilsV2.js.map +1 -1
- package/build/withdrawLiquidity.js +11 -5
- package/build/withdrawLiquidity.js.map +1 -1
- package/build/ytTrades.d.ts +7 -0
- package/build/ytTrades.js +163 -142
- package/build/ytTrades.js.map +1 -1
- package/package.json +2 -2
- package/src/addLiquidity.ts +1012 -38
- package/src/bisect.ts +22 -11
- package/src/index.ts +11 -5
- package/src/liquidityHistogram.ts +54 -9
- package/src/quote.ts +73 -95
- package/src/swap.ts +35 -19
- package/src/swapV2.ts +999 -0
- package/src/types.ts +55 -0
- package/src/utils.ts +24 -3
- package/src/utilsV2.ts +337 -0
- package/src/withdrawLiquidity.ts +12 -6
- package/src/ytTrades.ts +191 -172
- package/src/ytTradesLegacy.ts +419 -0
- package/build/swap-v2.d.ts +0 -20
- package/build/swap-v2.js +0 -261
- package/build/swap-v2.js.map +0 -1
- package/src/swapLegacy.ts +0 -272
package/build/ytTrades.js
CHANGED
|
@@ -9,19 +9,30 @@ exports.simulateSellYt = exports.simulateBuyYtWithSyIn = exports.simulateBuyYt =
|
|
|
9
9
|
* - Sell YT: Merge PT+YT → SY, then buy PT from pool to repay
|
|
10
10
|
*/
|
|
11
11
|
const bisect_1 = require("./bisect");
|
|
12
|
-
const
|
|
12
|
+
const swapV2_1 = require("./swapV2");
|
|
13
13
|
const types_1 = require("./types");
|
|
14
14
|
/**
|
|
15
|
-
* Helper function to convert PY to SY
|
|
16
|
-
* @param syExchangeRate - The SY exchange rate
|
|
15
|
+
* Helper function to convert PY to SY (floor)
|
|
16
|
+
* @param syExchangeRate - The SY exchange rate (SY value in terms of underlying)
|
|
17
17
|
* @param pyAmount - The PY (PT or YT) amount
|
|
18
|
-
* @returns The equivalent SY amount
|
|
18
|
+
* @returns The equivalent SY amount (floored)
|
|
19
19
|
*/
|
|
20
20
|
function pyToSy(syExchangeRate, pyAmount) {
|
|
21
21
|
if (syExchangeRate <= 0)
|
|
22
22
|
return 0;
|
|
23
23
|
return Math.floor(pyAmount / syExchangeRate);
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Helper function to convert PY to SY (ceil) - for when you need AT LEAST this much SY
|
|
27
|
+
* @param syExchangeRate - The SY exchange rate
|
|
28
|
+
* @param pyAmount - The PY (PT or YT) amount
|
|
29
|
+
* @returns The equivalent SY amount (ceiled)
|
|
30
|
+
*/
|
|
31
|
+
function pyToSyCeil(syExchangeRate, pyAmount) {
|
|
32
|
+
if (syExchangeRate <= 0)
|
|
33
|
+
return 0;
|
|
34
|
+
return Math.ceil(pyAmount / syExchangeRate);
|
|
35
|
+
}
|
|
25
36
|
/**
|
|
26
37
|
* Helper function to convert SY to PY
|
|
27
38
|
* @param syExchangeRate - The SY exchange rate
|
|
@@ -47,13 +58,12 @@ function syToPy(syExchangeRate, syAmount) {
|
|
|
47
58
|
function simulateBuyYt(marketState, args) {
|
|
48
59
|
const { ytOut, syExchangeRate, priceSpotLimit } = args;
|
|
49
60
|
// Calculate how much SY needs to be stripped to get the desired YT
|
|
50
|
-
//
|
|
51
|
-
const syToStrip =
|
|
52
|
-
// Stripping gives
|
|
61
|
+
// Use ceiling to ensure we strip enough SY
|
|
62
|
+
const syToStrip = pyToSyCeil(syExchangeRate, ytOut);
|
|
63
|
+
// Stripping gives equal amounts of PT and YT (1:1 ratio based on underlying value)
|
|
53
64
|
const ptFromStrip = ytOut;
|
|
54
65
|
// Simulate selling the PT to get SY back
|
|
55
|
-
|
|
56
|
-
const swapResult = (0, swap_1.simulateSwap)(marketState, {
|
|
66
|
+
const swapResult = (0, swapV2_1.simulateSwap)(marketState, {
|
|
57
67
|
direction: types_1.SwapDirection.PtToSy,
|
|
58
68
|
amountIn: ytOut,
|
|
59
69
|
priceSpotLimit,
|
|
@@ -75,6 +85,22 @@ function simulateBuyYt(marketState, args) {
|
|
|
75
85
|
};
|
|
76
86
|
}
|
|
77
87
|
exports.simulateBuyYt = simulateBuyYt;
|
|
88
|
+
/**
|
|
89
|
+
* Helper to calculate net SY cost for a given YT amount
|
|
90
|
+
*/
|
|
91
|
+
function calculateNetSyCost(marketState, ytAmount, syExchangeRate, priceSpotLimit) {
|
|
92
|
+
const syToStrip = pyToSyCeil(syExchangeRate, ytAmount);
|
|
93
|
+
const swapResult = (0, swapV2_1.simulateSwap)(marketState, {
|
|
94
|
+
direction: types_1.SwapDirection.PtToSy,
|
|
95
|
+
amountIn: ytAmount,
|
|
96
|
+
priceSpotLimit,
|
|
97
|
+
syExchangeRate,
|
|
98
|
+
isCurrentFlashSwap: true,
|
|
99
|
+
});
|
|
100
|
+
const syFromPtSale = swapResult.amountOut;
|
|
101
|
+
const netSyCost = syToStrip - syFromPtSale;
|
|
102
|
+
return { netSyCost, syToStrip, syFromPtSale };
|
|
103
|
+
}
|
|
78
104
|
/**
|
|
79
105
|
* Simulates buying YT tokens given a SY input amount
|
|
80
106
|
*
|
|
@@ -93,119 +119,139 @@ exports.simulateBuyYt = simulateBuyYt;
|
|
|
93
119
|
*/
|
|
94
120
|
function simulateBuyYtWithSyIn(marketState, args) {
|
|
95
121
|
const { syIn, syExchangeRate, priceSpotLimit } = args;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
//
|
|
122
|
+
if (syIn <= 0) {
|
|
123
|
+
throw new Error("syIn must be positive");
|
|
124
|
+
}
|
|
125
|
+
if (syExchangeRate <= 0) {
|
|
126
|
+
throw new Error("syExchangeRate must be positive");
|
|
127
|
+
}
|
|
128
|
+
// Lower bound: minimum meaningful YT amount
|
|
103
129
|
const minPossibleYt = 1;
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
const marketPtLiquidity = Number(marketState.financials.ptBalance);
|
|
130
|
+
// Buy-YT uses a flash-swap PT->SY path, so the tradeable size is determined by active
|
|
131
|
+
// tick liquidity, not by the idle PT balance stored on the market account.
|
|
107
132
|
const marketSyLiquidity = Number(marketState.financials.syBalance);
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
133
|
+
// Calculate cost at minimum YT to verify function behavior
|
|
134
|
+
let minCost;
|
|
135
|
+
try {
|
|
136
|
+
const minResult = calculateNetSyCost(marketState, minPossibleYt, syExchangeRate, priceSpotLimit);
|
|
137
|
+
minCost = minResult.netSyCost;
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
throw new Error("Market cannot support even minimum YT trade");
|
|
141
|
+
}
|
|
142
|
+
// If minimum cost already exceeds syIn, we can't do this trade
|
|
143
|
+
if (minCost > syIn) {
|
|
144
|
+
throw new Error(`Trade too small: minimum YT (${minPossibleYt}) costs ${minCost} SY, but only ${syIn} SY available`);
|
|
145
|
+
}
|
|
146
|
+
// Find upper bound using exponential search
|
|
147
|
+
// We need to find ytMax where netSyCost(ytMax) > syIn
|
|
148
|
+
let maxPossibleYt = Math.max(minPossibleYt + 1, syToPy(syExchangeRate, syIn)); // Start with naive estimate
|
|
116
149
|
let foundUpperBound = false;
|
|
117
|
-
let
|
|
118
|
-
|
|
119
|
-
|
|
150
|
+
let lastValidYt = minPossibleYt;
|
|
151
|
+
let lastValidCost = minCost;
|
|
152
|
+
// Exponential search to find upper bound
|
|
153
|
+
const maxAttempts = 40;
|
|
154
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
155
|
+
const testYt = Math.max(minPossibleYt + 1, Math.floor(maxPossibleYt));
|
|
120
156
|
try {
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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;
|
|
157
|
+
const result = calculateNetSyCost(marketState, testYt, syExchangeRate, priceSpotLimit);
|
|
158
|
+
if (result.netSyCost > syIn) {
|
|
159
|
+
// Found upper bound
|
|
160
|
+
maxPossibleYt = testYt;
|
|
144
161
|
foundUpperBound = true;
|
|
145
162
|
break;
|
|
146
163
|
}
|
|
164
|
+
// This YT amount is still affordable, save it
|
|
165
|
+
lastValidYt = testYt;
|
|
166
|
+
lastValidCost = result.netSyCost;
|
|
167
|
+
// Increase estimate using adaptive growth
|
|
168
|
+
// The closer lastValidCost is to syIn, the smaller the growth factor
|
|
169
|
+
const remainingBudget = syIn - lastValidCost;
|
|
170
|
+
const growthFactor = Math.max(1.5, Math.min(3, 1 + remainingBudget / Math.max(lastValidCost, 1)));
|
|
171
|
+
maxPossibleYt = Math.ceil(testYt * growthFactor);
|
|
147
172
|
}
|
|
148
173
|
catch (error) {
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
174
|
+
// Swap failed - we've exceeded what the market can handle
|
|
175
|
+
if (lastValidYt > minPossibleYt) {
|
|
176
|
+
// Use binary search between lastValidYt and testYt to find exact upper bound
|
|
177
|
+
let searchLo = lastValidYt;
|
|
178
|
+
let searchHi = testYt;
|
|
179
|
+
for (let i = 0; i < 10; i++) {
|
|
180
|
+
const mid = Math.floor((searchLo + searchHi) / 2);
|
|
181
|
+
try {
|
|
182
|
+
const midResult = calculateNetSyCost(marketState, mid, syExchangeRate, priceSpotLimit);
|
|
183
|
+
if (midResult.netSyCost > syIn) {
|
|
184
|
+
searchHi = mid;
|
|
185
|
+
foundUpperBound = true;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
searchLo = mid;
|
|
189
|
+
lastValidYt = mid;
|
|
190
|
+
lastValidCost = midResult.netSyCost;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
searchHi = mid;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (foundUpperBound) {
|
|
198
|
+
maxPossibleYt = searchHi;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
// Couldn't find upper bound - trade exceeds market capacity
|
|
202
|
+
throw new Error(`Trade exceeds market capacity: max affordable YT is ~${lastValidYt} (cost: ${lastValidCost}), ` +
|
|
203
|
+
`syIn = ${syIn}`);
|
|
204
|
+
}
|
|
205
|
+
break;
|
|
155
206
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
207
|
+
// Re-throw if we haven't found any valid YT amount
|
|
208
|
+
if (error instanceof Error) {
|
|
209
|
+
throw error;
|
|
159
210
|
}
|
|
160
|
-
|
|
161
|
-
break;
|
|
211
|
+
throw new Error("Failed to find valid YT range");
|
|
162
212
|
}
|
|
163
213
|
}
|
|
164
214
|
if (!foundUpperBound) {
|
|
165
|
-
throw new Error(`Could not find upper bound for YT amount
|
|
215
|
+
throw new Error(`Could not find upper bound for YT amount after ${maxAttempts} attempts. ` +
|
|
216
|
+
`Last valid: ${lastValidYt} (cost: ${lastValidCost}), syIn: ${syIn}`);
|
|
166
217
|
}
|
|
167
|
-
//
|
|
218
|
+
// Sanity check bounds
|
|
168
219
|
if (maxPossibleYt <= minPossibleYt) {
|
|
169
|
-
|
|
220
|
+
throw new Error(`Invalid bounds: min=${minPossibleYt}, max=${maxPossibleYt}`);
|
|
170
221
|
}
|
|
171
222
|
// Use bisection search to find the ytOut that results in netSyCost = syIn
|
|
172
|
-
//
|
|
173
|
-
const adaptiveEpsilon = Math.max(
|
|
174
|
-
|
|
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
|
-
}
|
|
223
|
+
// Epsilon should be small relative to the expected result magnitude
|
|
224
|
+
const adaptiveEpsilon = Math.max(1, syIn * 0.0001);
|
|
225
|
+
const maxIterations = 100; // Bisection converges fast with good bounds
|
|
183
226
|
const ytOut = (0, bisect_1.bisectSearch2)((ytGuess) => {
|
|
184
|
-
|
|
185
|
-
|
|
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;
|
|
227
|
+
const result = calculateNetSyCost(marketState, ytGuess, syExchangeRate, priceSpotLimit);
|
|
228
|
+
return result.netSyCost - syIn;
|
|
197
229
|
}, minPossibleYt, maxPossibleYt, adaptiveEpsilon, maxIterations);
|
|
198
230
|
if (ytOut === null) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
231
|
+
// This shouldn't happen if bounds are correct
|
|
232
|
+
// Provide detailed debug info
|
|
233
|
+
const minResult = calculateNetSyCost(marketState, minPossibleYt, syExchangeRate, priceSpotLimit);
|
|
234
|
+
let maxResult = null;
|
|
235
|
+
try {
|
|
236
|
+
maxResult = calculateNetSyCost(marketState, maxPossibleYt, syExchangeRate, priceSpotLimit);
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
// Max might fail
|
|
240
|
+
}
|
|
241
|
+
throw new Error(`Failed to converge: bounds [${minPossibleYt}, ${maxPossibleYt}], ` +
|
|
242
|
+
`f(min)=${minResult.netSyCost - syIn}, f(max)=${maxResult ? maxResult.netSyCost - syIn : "error"}, ` +
|
|
243
|
+
`syIn=${syIn}, epsilon=${adaptiveEpsilon}`);
|
|
202
244
|
}
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
ytOut,
|
|
245
|
+
// Return full result using the found ytOut
|
|
246
|
+
const result = simulateBuyYt(marketState, {
|
|
247
|
+
ytOut: Math.floor(ytOut), // Floor to ensure we don't over-promise
|
|
206
248
|
syExchangeRate,
|
|
207
249
|
priceSpotLimit,
|
|
208
250
|
});
|
|
251
|
+
if (marketSyLiquidity * syExchangeRate < result.ytOut * 2) {
|
|
252
|
+
throw new Error(`Insufficient SY liquidity in the market. Required: ${result.ytOut * 2}, Available: ${marketSyLiquidity}`);
|
|
253
|
+
}
|
|
254
|
+
return result;
|
|
209
255
|
}
|
|
210
256
|
exports.simulateBuyYtWithSyIn = simulateBuyYtWithSyIn;
|
|
211
257
|
/**
|
|
@@ -224,60 +270,35 @@ exports.simulateBuyYtWithSyIn = simulateBuyYtWithSyIn;
|
|
|
224
270
|
* @returns Simulation result with net SY received
|
|
225
271
|
*/
|
|
226
272
|
function simulateSellYt(marketState, args) {
|
|
227
|
-
const { ytIn, syExchangeRate, priceSpotLimit } = args;
|
|
273
|
+
const { ytIn, syExchangeRate, priceSpotLimit, safetyMarginBps = 0 } = args;
|
|
274
|
+
if (ytIn <= 0) {
|
|
275
|
+
throw new Error("ytIn must be positive");
|
|
276
|
+
}
|
|
228
277
|
// Check if there's sufficient PT liquidity
|
|
229
|
-
|
|
230
|
-
if (
|
|
231
|
-
throw new Error(`Insufficient PT liquidity in the market. Required: ${ytIn * 2}, Available: ${
|
|
278
|
+
const marketPtBalance = Number(marketState.financials.ptBalance);
|
|
279
|
+
if (marketPtBalance < ytIn * 2) {
|
|
280
|
+
throw new Error(`Insufficient PT liquidity in the market. Required: ${ytIn * 2}, Available: ${marketPtBalance}`);
|
|
232
281
|
}
|
|
233
|
-
// Merging PT + YT gives back the original SY
|
|
234
|
-
// The amount of PT needed equals ytIn (1:1 ratio)
|
|
282
|
+
// Merging PT + YT gives back the original SY (floor since you can't get fractional SY)
|
|
235
283
|
const syFromMerge = pyToSy(syExchangeRate, ytIn);
|
|
236
|
-
|
|
237
|
-
|
|
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");
|
|
284
|
+
if (syFromMerge <= 0) {
|
|
285
|
+
throw new Error(`Trade too small: merging ${ytIn} YT yields 0 SY`);
|
|
272
286
|
}
|
|
273
|
-
|
|
287
|
+
// On-chain uses pt_constraint + 2 to account for rounding, so we match that behavior
|
|
288
|
+
const ptNeeded = ytIn + 2;
|
|
289
|
+
// Match on-chain SellYt exactly: TradePtExactOut with pt_target = yt_in + 2 and SY budget = syFromMerge
|
|
290
|
+
const swapResult = (0, swapV2_1.simulateSwapExactOut)(marketState, {
|
|
274
291
|
direction: types_1.SwapDirection.SyToPt,
|
|
275
|
-
|
|
292
|
+
amountOut: ptNeeded,
|
|
276
293
|
priceSpotLimit,
|
|
277
294
|
syExchangeRate,
|
|
278
295
|
isCurrentFlashSwap: true,
|
|
296
|
+
amountInConstraint: syFromMerge,
|
|
279
297
|
});
|
|
280
|
-
|
|
298
|
+
// Optional conservative output buffer.
|
|
299
|
+
const rawNetSyReceived = syFromMerge - swapResult.amountInConsumed;
|
|
300
|
+
const safetyDeduction = safetyMarginBps > 0 ? Math.ceil((rawNetSyReceived * safetyMarginBps) / 10000) : 0;
|
|
301
|
+
const netSyReceived = rawNetSyReceived - safetyDeduction;
|
|
281
302
|
return {
|
|
282
303
|
ytIn,
|
|
283
304
|
netSyReceived,
|
package/build/ytTrades.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ytTrades.js","sourceRoot":"","sources":["../src/ytTrades.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;AACH,qCAAwC;AACxC,
|
|
1
|
+
{"version":3,"file":"ytTrades.js","sourceRoot":"","sources":["../src/ytTrades.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exponent-labs/market-three-math",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"main": "build/index.js",
|
|
5
5
|
"types": "build/index.d.ts",
|
|
6
6
|
"license": "AGPL-3.0",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"test:live": "ts-node examples/test-live-market.ts"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@exponent-labs/exponent-fetcher": "0.
|
|
13
|
+
"@exponent-labs/exponent-fetcher": "0.9.0",
|
|
14
14
|
"@solana/web3.js": "^1.95.8"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|