@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.
- package/CHANGELOG.md +8 -0
- package/README.md +197 -0
- package/build/addLiquidity.d.ts +67 -0
- package/build/addLiquidity.js +269 -0
- package/build/addLiquidity.js.map +1 -0
- package/build/bisect.d.ts +1 -0
- package/build/bisect.js +62 -0
- package/build/bisect.js.map +1 -0
- package/build/index.d.ts +24 -0
- package/build/index.js +76 -0
- package/build/index.js.map +1 -0
- package/build/liquidityHistogram.d.ts +50 -0
- package/build/liquidityHistogram.js +162 -0
- package/build/liquidityHistogram.js.map +1 -0
- package/build/quote.d.ts +18 -0
- package/build/quote.js +106 -0
- package/build/quote.js.map +1 -0
- package/build/swap-v2.d.ts +20 -0
- package/build/swap-v2.js +261 -0
- package/build/swap-v2.js.map +1 -0
- package/build/swap.d.ts +15 -0
- package/build/swap.js +249 -0
- package/build/swap.js.map +1 -0
- package/build/swapLegacy.d.ts +16 -0
- package/build/swapLegacy.js +229 -0
- package/build/swapLegacy.js.map +1 -0
- package/build/swapV2.d.ts +11 -0
- package/build/swapV2.js +406 -0
- package/build/swapV2.js.map +1 -0
- package/build/types.d.ts +73 -0
- package/build/types.js +9 -0
- package/build/types.js.map +1 -0
- package/build/utils.d.ts +119 -0
- package/build/utils.js +219 -0
- package/build/utils.js.map +1 -0
- package/build/utilsV2.d.ts +88 -0
- package/build/utilsV2.js +180 -0
- package/build/utilsV2.js.map +1 -0
- package/build/withdrawLiquidity.d.ts +8 -0
- package/build/withdrawLiquidity.js +174 -0
- package/build/withdrawLiquidity.js.map +1 -0
- package/build/ytTrades.d.ts +106 -0
- package/build/ytTrades.js +292 -0
- package/build/ytTrades.js.map +1 -0
- package/build/ytTradesLegacy.d.ts +106 -0
- package/build/ytTradesLegacy.js +292 -0
- package/build/ytTradesLegacy.js.map +1 -0
- package/examples/.env.example +1 -0
- package/examples/test-histogram-simple.ts +172 -0
- package/examples/test-histogram.ts +112 -0
- package/package.json +26 -0
- package/src/addLiquidity.ts +384 -0
- package/src/bisect.ts +72 -0
- package/src/index.ts +74 -0
- package/src/liquidityHistogram.ts +192 -0
- package/src/quote.ts +128 -0
- package/src/swap.ts +299 -0
- package/src/swapLegacy.ts +272 -0
- package/src/types.ts +80 -0
- package/src/utils.ts +235 -0
- package/src/withdrawLiquidity.ts +240 -0
- package/src/ytTrades.ts +419 -0
- package/tsconfig.json +17 -0
package/build/utilsV2.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getFeeFromAmount = exports.calculateFeeRate = exports.normalizedTimeRemaining = exports.TicksWrapper = exports.EffSnap = void 0;
|
|
4
|
+
const SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
|
|
5
|
+
const TICK_KEY_BASE_POINTS = 1_000_000;
|
|
6
|
+
/**
|
|
7
|
+
* Effective price snapshot
|
|
8
|
+
* Matches the Rust EffSnap struct
|
|
9
|
+
*/
|
|
10
|
+
class EffSnap {
|
|
11
|
+
timeFactor;
|
|
12
|
+
syExchangeRate;
|
|
13
|
+
constructor(timeFactor, syExchangeRate) {
|
|
14
|
+
this.timeFactor = timeFactor;
|
|
15
|
+
this.syExchangeRate = syExchangeRate;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Calculate effective price from spot price
|
|
19
|
+
* Rust: C(u) = u^(-(τ-1)) / (r * (τ - 1))
|
|
20
|
+
*/
|
|
21
|
+
getEffectivePrice(u) {
|
|
22
|
+
if (this.timeFactor === 1.0) {
|
|
23
|
+
throw new Error("time_factor cannot be 1.0");
|
|
24
|
+
}
|
|
25
|
+
return Math.pow(u, -this.timeFactor + 1.0) / (this.syExchangeRate * (this.timeFactor - 1.0));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Convert effective price back to spot price
|
|
29
|
+
* Rust: u = (r * C * (τ - 1))^(1/(1-τ))
|
|
30
|
+
*/
|
|
31
|
+
spotPriceFromEffectivePrice(cEff) {
|
|
32
|
+
const base = this.syExchangeRate * cEff * (this.timeFactor - 1.0);
|
|
33
|
+
return Math.pow(base, 1.0 / (1.0 - this.timeFactor));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.EffSnap = EffSnap;
|
|
37
|
+
/**
|
|
38
|
+
* TicksWrapper - wraps the ticks array and provides RB-tree-like operations
|
|
39
|
+
* This simulates the Rust RB-tree behavior using a sorted map
|
|
40
|
+
*/
|
|
41
|
+
class TicksWrapper {
|
|
42
|
+
ticksByKey; // key (apyBasePoints) -> Tick
|
|
43
|
+
sortedKeys; // sorted list of keys for successor/predecessor
|
|
44
|
+
currentSpotPrice;
|
|
45
|
+
currentTickKey; // Store key instead of array index
|
|
46
|
+
currentPrefixSum;
|
|
47
|
+
feeGrowthIndexGlobalPt;
|
|
48
|
+
feeGrowthIndexGlobalSy;
|
|
49
|
+
constructor(ticks) {
|
|
50
|
+
this.ticksByKey = new Map();
|
|
51
|
+
// Build map from apyBasePoints -> Tick
|
|
52
|
+
for (const tick of ticks.ticksTree) {
|
|
53
|
+
if (tick.apyBasePoints > 0) {
|
|
54
|
+
this.ticksByKey.set(tick.apyBasePoints, tick);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Get sorted keys for efficient successor/predecessor lookup
|
|
58
|
+
this.sortedKeys = Array.from(this.ticksByKey.keys()).sort((a, b) => a - b);
|
|
59
|
+
this.currentSpotPrice = ticks.currentSpotPrice;
|
|
60
|
+
this.currentPrefixSum = ticks.currentPrefixSum;
|
|
61
|
+
this.feeGrowthIndexGlobalPt = ticks.feeGrowthIndexGlobalPt;
|
|
62
|
+
this.feeGrowthIndexGlobalSy = ticks.feeGrowthIndexGlobalSy;
|
|
63
|
+
// Convert currentTick (1-based index) to key
|
|
64
|
+
// In Rust, currentTick is stored as 1-based index into the ticks tree
|
|
65
|
+
// We need to find the corresponding key (apyBasePoints)
|
|
66
|
+
const currentTickFromArray = ticks.ticksTree[ticks.currentTick - 1];
|
|
67
|
+
if (currentTickFromArray && currentTickFromArray.apyBasePoints > 0) {
|
|
68
|
+
this.currentTickKey = currentTickFromArray.apyBasePoints;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
// Fallback: find tick with spot price closest to currentSpotPrice
|
|
72
|
+
this.currentTickKey = this.findTickKeyBySpotPrice(ticks.currentSpotPrice);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Find tick key by spot price (for initialization)
|
|
77
|
+
*/
|
|
78
|
+
findTickKeyBySpotPrice(spotPrice) {
|
|
79
|
+
let closestKey = this.sortedKeys[0] || 0;
|
|
80
|
+
// let prevKey: number | null = null
|
|
81
|
+
// Iterate through sorted keys to ensure order
|
|
82
|
+
for (const key of this.sortedKeys) {
|
|
83
|
+
const tick = this.ticksByKey.get(key);
|
|
84
|
+
if (!tick)
|
|
85
|
+
continue;
|
|
86
|
+
const diff = spotPrice - tick.impliedRate;
|
|
87
|
+
if (diff < 0) {
|
|
88
|
+
// If diff is negative, return the previous key (the one we just passed)
|
|
89
|
+
return closestKey;
|
|
90
|
+
}
|
|
91
|
+
// Update closest key and remember previous
|
|
92
|
+
// prevKey = closestKey
|
|
93
|
+
closestKey = key;
|
|
94
|
+
}
|
|
95
|
+
return closestKey;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get tick by key (apyBasePoints)
|
|
99
|
+
* Equivalent to Rust's ticks_tree.get_node(idx).value
|
|
100
|
+
*/
|
|
101
|
+
getTickByKey(key) {
|
|
102
|
+
return this.ticksByKey.get(key) ?? null;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get spot price for a tick key
|
|
106
|
+
* Equivalent to Rust's ticks.get_spot_price(idx)
|
|
107
|
+
* In Rust: spot_price = 1.0 + key / TICK_KEY_BASE_POINTS
|
|
108
|
+
*/
|
|
109
|
+
getSpotPrice(key) {
|
|
110
|
+
const tick = this.ticksByKey.get(key);
|
|
111
|
+
if (tick) {
|
|
112
|
+
return tick.impliedRate;
|
|
113
|
+
}
|
|
114
|
+
// Fallback calculation if tick not found
|
|
115
|
+
return 1.0 + key / TICK_KEY_BASE_POINTS;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Find successor key (next tick with greater apyBasePoints)
|
|
119
|
+
* Equivalent to Rust's ticks.successor_idx(idx)
|
|
120
|
+
*/
|
|
121
|
+
successorKey(currentKey) {
|
|
122
|
+
const idx = this.sortedKeys.findIndex((k) => k > currentKey);
|
|
123
|
+
return idx !== -1 ? this.sortedKeys[idx] : null;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Find predecessor key (previous tick with smaller apyBasePoints)
|
|
127
|
+
* Equivalent to Rust's ticks.predecessor_idx(idx)
|
|
128
|
+
*/
|
|
129
|
+
predecessorKey(currentKey) {
|
|
130
|
+
// Find the largest key that is smaller than currentKey
|
|
131
|
+
for (let i = this.sortedKeys.length - 1; i >= 0; i--) {
|
|
132
|
+
if (this.sortedKeys[i] < currentKey) {
|
|
133
|
+
return this.sortedKeys[i];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get principal values for a tick
|
|
140
|
+
*/
|
|
141
|
+
getPrincipals(key) {
|
|
142
|
+
const tick = this.ticksByKey.get(key);
|
|
143
|
+
return {
|
|
144
|
+
principalPt: tick?.principalPt ?? 0n,
|
|
145
|
+
principalSy: tick?.principalSy ?? 0n,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get liquidity net for a tick
|
|
150
|
+
*/
|
|
151
|
+
getLiquidityNet(key) {
|
|
152
|
+
const tick = this.ticksByKey.get(key);
|
|
153
|
+
return tick?.liquidityNet ?? 0n;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
exports.TicksWrapper = TicksWrapper;
|
|
157
|
+
/**
|
|
158
|
+
* Calculate normalized time remaining
|
|
159
|
+
*/
|
|
160
|
+
function normalizedTimeRemaining(secondsRemaining) {
|
|
161
|
+
return secondsRemaining / SECONDS_PER_YEAR;
|
|
162
|
+
}
|
|
163
|
+
exports.normalizedTimeRemaining = normalizedTimeRemaining;
|
|
164
|
+
/**
|
|
165
|
+
* Calculate current fee rate
|
|
166
|
+
*/
|
|
167
|
+
function calculateFeeRate(lnFeeRateRoot, secondsRemaining) {
|
|
168
|
+
const timeFactor = normalizedTimeRemaining(secondsRemaining);
|
|
169
|
+
return Math.exp(lnFeeRateRoot * timeFactor);
|
|
170
|
+
}
|
|
171
|
+
exports.calculateFeeRate = calculateFeeRate;
|
|
172
|
+
/**
|
|
173
|
+
* Calculate fee from amount
|
|
174
|
+
* Mirrors Rust: ((amount as f64) * (fee_rate - 1.0)).ceil() as u64
|
|
175
|
+
*/
|
|
176
|
+
function getFeeFromAmount(amount, feeRate) {
|
|
177
|
+
return Math.ceil(amount * (feeRate - 1.0));
|
|
178
|
+
}
|
|
179
|
+
exports.getFeeFromAmount = getFeeFromAmount;
|
|
180
|
+
//# sourceMappingURL=utilsV2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utilsV2.js","sourceRoot":"","sources":["../src/utilsV2.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { LpPositionCLMM, MarketThree, Ticks } from "@exponent-labs/exponent-fetcher";
|
|
2
|
+
/**
|
|
3
|
+
* Returns the total PT and SY amounts that would be removed from a position
|
|
4
|
+
*/
|
|
5
|
+
export declare function getPtAndSyOnWithdrawLiquidity(marketEmissions: MarketThree["emissions"], ticks: Ticks, position: LpPositionCLMM, liquidityToRemove: bigint): {
|
|
6
|
+
totalPtOut: bigint;
|
|
7
|
+
totalSyOut: bigint;
|
|
8
|
+
};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getPtAndSyOnWithdrawLiquidity = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
function projectAnchorSharesToCurrentTicks(ticks, rootShares) {
|
|
6
|
+
const SENTINEL = 0xffffffff; // Sentinel value for tree traversal (matches Rust implementation)
|
|
7
|
+
const stack = [...rootShares]; // Clone the trackers array
|
|
8
|
+
const newShares = []; // This will hold the leaf shares
|
|
9
|
+
while (stack.length > 0) {
|
|
10
|
+
const principalShare = stack.pop();
|
|
11
|
+
// Find the tick node for this share
|
|
12
|
+
const tickNode = ticks.ticksTree.at(principalShare.tickIdx - 1) ?? null;
|
|
13
|
+
if (!tickNode) {
|
|
14
|
+
//? Tick node not found for tickIdx
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
const lastSplitEpoch = tickNode.lastSplitEpoch;
|
|
18
|
+
// Check if we need to split this share (if the tick has been split since this share was created)
|
|
19
|
+
if (principalShare.splitEpoch < lastSplitEpoch) {
|
|
20
|
+
const rightIndex = principalShare.rightTickIdx;
|
|
21
|
+
if (rightIndex !== SENTINEL) {
|
|
22
|
+
// Find the successor tick (the split point)
|
|
23
|
+
const splitedIndex = (0, utils_1.getSuccessorTickByIdx)(ticks, principalShare.tickIdx);
|
|
24
|
+
if (splitedIndex === null) {
|
|
25
|
+
//? No successor tick found for splitting
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const tickSpotPrice = tickNode.impliedRate;
|
|
29
|
+
const rightTickNode = ticks.ticksTree.at(rightIndex - 1) ?? null;
|
|
30
|
+
const splitedTickNode = ticks.ticksTree.at(splitedIndex - 1) ?? null;
|
|
31
|
+
if (!rightTickNode || !splitedTickNode) {
|
|
32
|
+
//? Could not find right or split tick nodes
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// Calculate the proportions based on spot price ranges
|
|
36
|
+
const splitedFullRange = rightTickNode.impliedRate - tickSpotPrice;
|
|
37
|
+
const currentSplitRange = splitedTickNode.impliedRate - tickSpotPrice;
|
|
38
|
+
// Calculate how much LP share goes to the left portion
|
|
39
|
+
const leftShare = Math.floor(Number(principalShare.lpShare) * (currentSplitRange / splitedFullRange));
|
|
40
|
+
// Create new emission trackers with staged reset to 0
|
|
41
|
+
const newEmissions = principalShare.emissions.map((tracker) => ({
|
|
42
|
+
staged: 0n,
|
|
43
|
+
lastSeenIndex: tracker.lastSeenIndex,
|
|
44
|
+
}));
|
|
45
|
+
// Calculate the migrated share (right portion)
|
|
46
|
+
const migratedShare = principalShare.lpShare - BigInt(leftShare);
|
|
47
|
+
// Update the current share to be the left portion
|
|
48
|
+
principalShare.lpShare = BigInt(leftShare);
|
|
49
|
+
principalShare.rightTickIdx = splitedIndex;
|
|
50
|
+
// Push the right portion back onto the stack for further processing
|
|
51
|
+
stack.push({
|
|
52
|
+
tickIdx: splitedIndex,
|
|
53
|
+
rightTickIdx: rightIndex,
|
|
54
|
+
splitEpoch: principalShare.splitEpoch,
|
|
55
|
+
lpShare: migratedShare,
|
|
56
|
+
emissions: newEmissions,
|
|
57
|
+
});
|
|
58
|
+
// Update the split epoch to mark this share as processed
|
|
59
|
+
principalShare.splitEpoch = lastSplitEpoch;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Error: we have a split range but no right index
|
|
63
|
+
//? No right index for split range
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Add the processed share to the result
|
|
68
|
+
newShares.push(principalShare);
|
|
69
|
+
}
|
|
70
|
+
// Reverse to maintain the original order (since we used a stack)
|
|
71
|
+
newShares.reverse();
|
|
72
|
+
return newShares;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* TypeScript version of update_lp_position_shares from Rust
|
|
76
|
+
* Recompute and update the LP position's share trackers to reflect current ticks state
|
|
77
|
+
*
|
|
78
|
+
* @param market - The market account containing emission indices
|
|
79
|
+
* @param ticks - The ticks state (must be TicksExtended with emission data)
|
|
80
|
+
* @param position - The LP position with share trackers to update
|
|
81
|
+
*
|
|
82
|
+
*/
|
|
83
|
+
function updateLpPositionShares(marketEmissions, ticks, position) {
|
|
84
|
+
// Get market emission indices (last seen indices from market's emission trackers)
|
|
85
|
+
// Market has emissions.trackers array with lpShareIndex for each emission
|
|
86
|
+
const marketEmissionIndices = marketEmissions.trackers.map((tracker) => tracker.lpShareIndex);
|
|
87
|
+
// Project anchor shares to current ticks
|
|
88
|
+
// This handles tick splitting that may have occurred since the position was created
|
|
89
|
+
const recomputedShares = projectAnchorSharesToCurrentTicks(ticks, position.shareTrackers);
|
|
90
|
+
// Iterate through each share and update
|
|
91
|
+
for (const share of recomputedShares) {
|
|
92
|
+
const myShares = share.lpShare;
|
|
93
|
+
// Find the tick node in the ticks tree
|
|
94
|
+
const tickNode = ticks.ticksTree.at(share.tickIdx - 1) ?? null;
|
|
95
|
+
if (!tickNode) {
|
|
96
|
+
//? Tick node not found for provided tickIdx
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
// Update tick emissions with market emission indices
|
|
100
|
+
// In Rust: node_mut.value.update_tick_emissions(market_emission_indices)
|
|
101
|
+
for (let i = 0; i < marketEmissionIndices.length; i++) {
|
|
102
|
+
if (tickNode.emissions[i]) {
|
|
103
|
+
tickNode.emissions[i].lastSeenIndex = marketEmissionIndices[i];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Accrue fees and emissions when removing
|
|
107
|
+
// In Rust: share.accrue_fees_emissions_when_remove(&node_mut.value, my_shares)
|
|
108
|
+
// This updates the share's emission trackers based on the tick's emission state
|
|
109
|
+
// and the number of LP shares
|
|
110
|
+
for (let i = 0; i < share.emissions.length; i++) {
|
|
111
|
+
const shareTracker = share.emissions[i];
|
|
112
|
+
const tickTracker = tickNode.emissions[i];
|
|
113
|
+
if (shareTracker && tickTracker) {
|
|
114
|
+
// Calculate accrued emissions based on index difference and LP shares
|
|
115
|
+
const indexDelta = tickTracker.lastSeenIndex - shareTracker.lastSeenIndex;
|
|
116
|
+
const accruedEmissions = Number(myShares) * indexDelta;
|
|
117
|
+
// Update staged emissions
|
|
118
|
+
shareTracker.staged += BigInt(Math.floor(accruedEmissions));
|
|
119
|
+
shareTracker.lastSeenIndex = tickTracker.lastSeenIndex;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Update split epoch
|
|
123
|
+
share.splitEpoch = tickNode.lastSplitEpoch;
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
...position,
|
|
127
|
+
shareTrackers: recomputedShares,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Calculate the total PT and SY amounts that would be removed from a position
|
|
132
|
+
* without actually modifying any state.
|
|
133
|
+
*
|
|
134
|
+
* TypeScript version based on Rust remove_liquidity logic
|
|
135
|
+
*
|
|
136
|
+
* @param position - The LP position to calculate removal amounts for
|
|
137
|
+
* @param ticks - The ticks data structure containing tick information
|
|
138
|
+
* @param liquidityToRemove - The amount of liquidity to remove (in L units)
|
|
139
|
+
* @returns Object with totalPtOut and totalSyOut
|
|
140
|
+
*/
|
|
141
|
+
function calculatePtSyRemoval(position, ticks, liquidityToRemove) {
|
|
142
|
+
let totalPtOut = 0n;
|
|
143
|
+
let totalSyOut = 0n;
|
|
144
|
+
for (const share of position.shareTrackers) {
|
|
145
|
+
const myShares = share.lpShare;
|
|
146
|
+
const tickNode = ticks.ticksTree.at(share.tickIdx - 1) ?? null;
|
|
147
|
+
if (!tickNode) {
|
|
148
|
+
//? Tick node not found for provided tickIdx
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const supply = tickNode.principalShareSupply;
|
|
152
|
+
// Calculate burn shares: r = l_remove / pos.L
|
|
153
|
+
// burn_shares = my_shares * liquidity_to_remove / position.lp_balance
|
|
154
|
+
const burnShares = (myShares * liquidityToRemove) / position.lpBalance;
|
|
155
|
+
// Calculate PT output for this tick
|
|
156
|
+
// pt_out = principal_pt * burn_shares / supply
|
|
157
|
+
const ptOut = (tickNode.principalPt * burnShares) / supply;
|
|
158
|
+
// Calculate SY output for this tick
|
|
159
|
+
// sy_out = principal_sy * burn_shares / supply
|
|
160
|
+
const syOut = (tickNode.principalSy * burnShares) / supply;
|
|
161
|
+
totalPtOut += ptOut;
|
|
162
|
+
totalSyOut += syOut;
|
|
163
|
+
}
|
|
164
|
+
return { totalPtOut, totalSyOut };
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Returns the total PT and SY amounts that would be removed from a position
|
|
168
|
+
*/
|
|
169
|
+
function getPtAndSyOnWithdrawLiquidity(marketEmissions, ticks, position, liquidityToRemove) {
|
|
170
|
+
const updatedPosition = updateLpPositionShares(marketEmissions, ticks, position);
|
|
171
|
+
return calculatePtSyRemoval(updatedPosition, ticks, liquidityToRemove);
|
|
172
|
+
}
|
|
173
|
+
exports.getPtAndSyOnWithdrawLiquidity = getPtAndSyOnWithdrawLiquidity;
|
|
174
|
+
//# sourceMappingURL=withdrawLiquidity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withdrawLiquidity.js","sourceRoot":"","sources":["../src/withdrawLiquidity.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;
|