@catalabs/catalyst-sdk
Version:
Catalyst AMM SDK
477 lines • 26.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sendAsset = sendAsset;
exports.receiveAsset = receiveAsset;
exports.getImmediatePrice = getImmediatePrice;
exports.depositMixed = depositMixed;
exports.withdrawEqual = withdrawEqual;
exports.solvWithdrawEqual = solvWithdrawEqual;
exports.withdrawMixed = withdrawMixed;
exports.estimateImbalanceLossDeposit = estimateImbalanceLossDeposit;
exports.estimateImbalanceLossWithdraw = estimateImbalanceLossWithdraw;
exports.findOptimalLiquiditySwaps = findOptimalLiquiditySwaps;
exports.findOptimalDepositValues = findOptimalDepositValues;
exports.balancedWithdrawalMacro = balancedWithdrawalMacro;
exports.findOptimalWithdrawLiquiditySwaps = findOptimalWithdrawLiquiditySwaps;
exports.distributeVaultTokenValue = distributeVaultTokenValue;
exports.computeEstimatedOutGivenPercentageWithdrawal = computeEstimatedOutGivenPercentageWithdrawal;
exports.findMeExpectedWithdrawnUnits = findMeExpectedWithdrawnUnits;
const liquidity_amplified_functions_1 = require("./amplified/liquidity.amplified.functions");
const math_amplified_functions_1 = require("./amplified/math.amplified.functions");
const math_amplified_integrals_1 = require("./amplified/math.amplified.integrals");
const math_lib_1 = require("./math.lib");
const math_utils_1 = require("./math.utils");
const liquidity_volatile_functions_1 = require("./volatile/liquidity.volatile.functions");
const math_volatile_functions_1 = require("./volatile/math.volatile.functions");
const math_volatile_integrals_1 = require("./volatile/math.volatile.integrals");
function sendAsset(fromBalance, input, fromWeight, amp) {
if (fromBalance === 0n) {
return 0n;
}
if (amp === math_lib_1.WAD) {
return (0, math_volatile_functions_1.sendAssetVol)(fromBalance, input, fromWeight);
}
else if (amp < math_lib_1.WAD) {
return (0, math_amplified_functions_1.sendAssetAmp)(fromBalance, input, fromWeight, amp);
}
else {
throw new Error('Amplification outside range [0, 1]');
}
}
function receiveAsset(toBalance, input, toWeight, amp) {
if (toBalance === 0n) {
return 0n;
}
if (amp === math_lib_1.WAD) {
return (0, math_volatile_functions_1.receiveAssetVol)(toBalance, input, toWeight);
}
else if (amp < math_lib_1.WAD) {
return (0, math_amplified_functions_1.receiveAssetAmp)(toBalance, input, toWeight, amp);
}
else {
throw new Error('Amplification outside range [0, 1]');
}
}
function getImmediatePrice(balanceFrom, balanceTo, weightFrom, weightTo, amplification, escrowTo = 0n) {
const adjustedBalance = balanceTo - escrowTo;
if (amplification === math_lib_1.WAD) {
return (adjustedBalance * weightFrom * math_lib_1.WAD) / (balanceFrom * weightTo);
}
else {
let num = adjustedBalance * weightTo;
num = (0, math_lib_1.powWad)(num, amplification);
let denom = balanceFrom * weightFrom;
denom = (0, math_lib_1.powWad)(denom, amplification);
return (num * weightFrom * math_lib_1.WAD) / (denom * weightTo);
}
}
function depositMixed(vault, depositAmounts) {
if (depositAmounts.length !== vault.balances.length) {
throw new Error('Different length between tokenAmounts and PoolBalance');
}
if (depositAmounts.length !== vault.weights.length) {
throw new Error('Different length between tokenAmounts and tokenWeights');
}
let U = 0n;
for (let i = 0; i < depositAmounts.length; i++) {
U +=
vault.amplification === math_lib_1.WAD
? (0, math_volatile_integrals_1.calcPriceCurveAreaVol)(depositAmounts[i], vault.balances[i], vault.weights[i])
: (0, math_amplified_integrals_1.calcPriceCurveAreaAmp)(depositAmounts[i], vault.balances[i], vault.weights[i], math_lib_1.WAD - vault.amplification);
}
U = (U * (math_lib_1.WAD - vault.vaultFee)) / math_lib_1.WAD;
let vaultTokens;
if (vault.amplification === math_lib_1.WAD) {
let wsum = 0n;
for (const weight of vault.weights) {
wsum = wsum + weight;
}
vaultTokens = (0, math_volatile_integrals_1.calcUnitsToVaultTokensVol)(U, vault.totalSupply, wsum);
}
else {
vaultTokens = (0, math_amplified_integrals_1.calcUnitsToVaultTokensAmp)(U, vault.totalSupply, vault.balances, vault.weights, vault.unitTracker, vault.amplification);
}
return vaultTokens;
}
function withdrawEqual(vault, vaultTokens) {
if (vault.amplification === math_lib_1.WAD) {
return (0, math_volatile_functions_1.withdrawEqualVol)(vaultTokens, vault.totalSupply, vault.escrowedVaultTokens, vault.weights, vault.balances, vault.escrowedTokens);
}
else {
return (0, math_amplified_functions_1.withdrawEqualAmp)(vaultTokens, vault.totalSupply, vault.escrowedVaultTokens, vault.weights, vault.balances, vault.escrowedTokens, vault.amplification, vault.unitTracker);
}
}
function solvWithdrawEqual(vault, referenceTokenWithdraw, referenceTokenIndex) {
if (vault.amplification === math_lib_1.WAD) {
return (0, math_volatile_functions_1.solvWithdrawEqualVol)(referenceTokenWithdraw, referenceTokenIndex, vault.totalSupply, vault.escrowedVaultTokens, vault.weights, vault.balances, vault.escrowedTokens);
}
else {
return (0, math_amplified_functions_1.solvWithdrawEqualAmp)(referenceTokenWithdraw, referenceTokenIndex, vault.totalSupply, vault.escrowedVaultTokens, vault.weights, vault.balances, vault.escrowedTokens, vault.amplification, vault.unitTracker);
}
}
function withdrawMixed(vault, vaultTokens, withdrawRatio) {
if (vault.amplification === math_lib_1.WAD) {
return (0, math_volatile_functions_1.withdrawMixedVol)(vaultTokens, (0, math_utils_1.weightedToProgressRatio)(withdrawRatio), vault.totalSupply, vault.escrowedVaultTokens, vault.weights, vault.balances, vault.escrowedTokens);
}
else {
return (0, math_amplified_functions_1.withdrawMixedAmp)(vaultTokens, (0, math_utils_1.weightedToProgressRatio)(withdrawRatio), vault.totalSupply, vault.escrowedVaultTokens, vault.weights, vault.balances, vault.escrowedTokens, vault.amplification, vault.unitTracker);
}
}
function estimateImbalanceLossDeposit(vaults, userDeposits) {
const referenceAssetBalance = vaults[0].balances[0];
const referenceAssetWeight = vaults[0].weights[0];
let vaultTokenEquivValue = 0n;
let depositedTokenValue = 0n;
for (let vaultIndex = 0; vaultIndex < vaults.length; ++vaultIndex) {
const vault = vaults[vaultIndex];
const userDeposit = userDeposits[vaultIndex];
const vaultTokens = depositMixed(vault, userDeposit);
const vaultCopy = { ...vault };
vaultCopy.balances = vault.balances.map((pb, i) => pb + userDeposit[i]);
vaultCopy.totalSupply = vault.totalSupply + vaultTokens;
const vaultTokenEquiv = withdrawEqual(vaultCopy, vaultTokens);
for (let assetIndex = 0; assetIndex < vault.balances.length; ++assetIndex) {
const price = getImmediatePrice(referenceAssetBalance, vault.balances[assetIndex], referenceAssetWeight, vault.weights[assetIndex], vault.amplification);
depositedTokenValue =
depositedTokenValue + (price * userDeposit[assetIndex]) / math_lib_1.WAD;
vaultTokenEquivValue =
vaultTokenEquivValue + (price * vaultTokenEquiv[assetIndex]) / math_lib_1.WAD;
}
}
return (vaultTokenEquivValue * math_lib_1.WAD) / depositedTokenValue;
}
function estimateImbalanceLossWithdraw(vaults, vaultTokens, withdrawRatios) {
const referenceAssetBalance = vaults[0].balances[0];
const referenceAssetWeight = vaults[0].weights[0];
let tokensMixedValue = 0n;
let tokensEqualValue = 0n;
for (let vaultIndex = 0; vaultIndex < vaults.length; ++vaultIndex) {
const vault = vaults[vaultIndex];
const withdrawRatio = withdrawRatios[vaultIndex];
const vaultToken = vaultTokens[vaultIndex];
const tokensEqual = withdrawEqual(vault, vaultToken);
const tokensMixed = withdrawMixed(vault, vaultToken, withdrawRatio);
for (let assetIndex = 0; assetIndex < vault.balances.length; ++assetIndex) {
const price = getImmediatePrice(referenceAssetBalance, vault.balances[assetIndex], referenceAssetWeight, vault.weights[assetIndex], vault.amplification);
tokensEqualValue =
tokensEqualValue + (price * tokensEqual[assetIndex]) / math_lib_1.WAD;
tokensMixedValue =
tokensMixedValue + (price * tokensMixed[assetIndex]) / math_lib_1.WAD;
}
}
return (tokensMixedValue * math_lib_1.WAD) / tokensEqualValue;
}
function findOptimalLiquiditySwaps(vaults, userDeposit) {
const boughtUnits = vaults[0].amplification === math_lib_1.WAD
? (0, liquidity_volatile_functions_1.assetsToUnitsVolatile)(vaults, userDeposit, true)
: (0, liquidity_amplified_functions_1.assetsToUnitsAmplified)(vaults, userDeposit, true);
const unitSwaps = vaults[0].amplification === math_lib_1.WAD
? (0, liquidity_volatile_functions_1.findOptimalSwapsVolatile)(vaults, boughtUnits, boughtUnits.map(() => 0n))
: (0, liquidity_amplified_functions_1.findOptimalSwapsAmplified)(vaults, boughtUnits, boughtUnits.map(() => 0n));
const expectedVaultTokens = [];
const vaultsPostDeposit = vaults.map((v, vi) => {
const vaultCopy = { ...v };
const vaultTokens = depositMixed(vaultCopy, userDeposit[vi]);
expectedVaultTokens.push(vaultTokens);
vaultCopy.totalSupply = vaultCopy.totalSupply + vaultTokens;
vaultCopy.balances = vaultCopy.balances.map((b, bi) => b + userDeposit[vi][bi]);
return vaultCopy;
});
const vaultsPostDepositCopy = vaultsPostDeposit.map((e) => {
return { ...e };
});
const rawVaultTokenSwaps = unitSwaps.map((swap) => {
const U = swap.units;
const fromVault = vaultsPostDeposit[swap.from];
const toVault = vaultsPostDeposit[swap.to];
const vaultTokensSent = fromVault.amplification === math_lib_1.WAD
? (0, math_volatile_integrals_1.calcUnitsForVaultTokensVol)(U, fromVault.totalSupply, (0, math_utils_1.bigNumberSum)(fromVault.weights))
: (0, math_amplified_integrals_1.calcUnitsForVaultTokensAmp)(U, fromVault.totalSupply, fromVault.balances, fromVault.weights, fromVault.unitTracker, fromVault.amplification);
const vaultTokensReceived = fromVault.amplification === math_lib_1.WAD
? (0, math_volatile_integrals_1.calcUnitsToVaultTokensVol)(U, toVault.totalSupply, (0, math_utils_1.bigNumberSum)(toVault.weights))
: (0, math_amplified_integrals_1.calcUnitsToVaultTokensAmp)(U, toVault.totalSupply, toVault.balances, toVault.weights, toVault.unitTracker, toVault.amplification);
expectedVaultTokens[swap.from] =
expectedVaultTokens[swap.from] - vaultTokensSent;
expectedVaultTokens[swap.to] =
expectedVaultTokens[swap.to] + vaultTokensReceived;
fromVault.totalSupply = fromVault.totalSupply - vaultTokensSent;
toVault.totalSupply = toVault.totalSupply + vaultTokensReceived;
if (fromVault.amplification !== math_lib_1.WAD) {
fromVault.unitTracker = fromVault.unitTracker + U;
}
if (toVault.amplification !== math_lib_1.WAD) {
toVault.unitTracker = toVault.unitTracker - U;
}
return { ...swap, vaultTokensSent, vaultTokensReceived };
});
const postBalance = [];
for (let i = 0; i < expectedVaultTokens.length; ++i) {
postBalance.push(withdrawEqual(vaultsPostDeposit[i], expectedVaultTokens[i]));
}
const deltaTokens = [];
for (let i = 0; i < expectedVaultTokens.length; ++i) {
const deltaWithinVault = [];
for (let j = 0; j < userDeposit[i].length; ++j) {
deltaWithinVault.push(postBalance[i][j] - userDeposit[i][j]);
}
deltaTokens.push(deltaWithinVault);
}
const negativeDeltaTokens = deltaTokens.map((vaultDeltaTokens) => vaultDeltaTokens.map((dt) => (dt < 0n ? dt * -1n : 0n)));
const unitsSwappedInput = vaults[0].amplification === math_lib_1.WAD
? (0, liquidity_volatile_functions_1.assetsToUnitsVolatile)(vaults, negativeDeltaTokens, false)
: (0, liquidity_amplified_functions_1.assetsToUnitsAmplified)(vaults, negativeDeltaTokens, false);
const withdrawalRatiosInput = unitsSwappedInput.map((unitsBought) => {
let vaultBoughtUnitSum = 0n;
const withdrawRatios = [];
for (const assetBought of unitsBought) {
vaultBoughtUnitSum = vaultBoughtUnitSum + assetBought;
if (vaultBoughtUnitSum === 0n) {
withdrawRatios.push(0n);
}
else {
withdrawRatios.push((assetBought * math_lib_1.WAD) / vaultBoughtUnitSum);
}
}
return withdrawRatios;
});
const vaultTokenSwapsWithInputs = rawVaultTokenSwaps.map((swap) => {
const fromVaultPostDeposit = vaultsPostDepositCopy[swap.from];
const equivalentInput = withdrawMixed(fromVaultPostDeposit, swap.vaultTokensSent, withdrawalRatiosInput[swap.from]);
return { ...swap, equivalentInput };
});
const positiveDeltaTokens = deltaTokens.map((vaultDeltaTokens) => vaultDeltaTokens.map((dt) => (dt > 0n ? dt : 0n)));
const unitsSwappedOutput = vaults[0].amplification === math_lib_1.WAD
? (0, liquidity_volatile_functions_1.assetsForUnitsVolatile)(vaults, positiveDeltaTokens)
: (0, liquidity_amplified_functions_1.assetsForUnitsAmplified)(vaults, positiveDeltaTokens);
const withdrawalRatiosOutput = unitsSwappedOutput.map((unitsBought) => {
let vaultBoughtUnitSum = 0n;
const withdrawRatios = [];
for (const assetBought of unitsBought) {
vaultBoughtUnitSum = vaultBoughtUnitSum + assetBought;
if (vaultBoughtUnitSum === 0n) {
withdrawRatios.push(0n);
}
else {
withdrawRatios.push((assetBought * math_lib_1.WAD) / vaultBoughtUnitSum);
}
}
return withdrawRatios;
});
const vaultTokenSwaps = vaultTokenSwapsWithInputs.map((swap) => {
const toVaultPostDeposit = vaultsPostDeposit[swap.to];
const equivalentOutput = (0, math_utils_1.bigNumberSum)(withdrawalRatiosOutput[swap.to]) === 0n
? withdrawalRatiosOutput.map((_) => 0n)
: withdrawMixed(toVaultPostDeposit, swap.vaultTokensReceived, withdrawalRatiosOutput[swap.to]);
return { ...swap, equivalentOutput };
});
return {
vaultTokenSwaps,
expectedVaultTokens,
vaultsPostDeposit,
postBalance,
};
}
function findOptimalDepositValues(vaults, userBalances, userInputs) {
const ratios = [];
let reference = undefined;
for (const vault of vaults) {
const vaultRatios = [];
let i = 0;
for (const token_balance of vault.balances) {
let localReference;
const assetWeight = vault.weights[i];
if (vault.amplification === math_lib_1.WAD) {
if (reference === undefined) {
reference = token_balance;
localReference = reference;
}
else {
localReference = token_balance;
}
}
else {
if (reference === undefined) {
reference =
(0, math_lib_1.powWad)(token_balance * vault.weights[i], vault.amplification) /
assetWeight;
localReference = reference;
}
else {
localReference =
(0, math_lib_1.powWad)(token_balance * vault.weights[i], vault.amplification) /
assetWeight;
}
}
vaultRatios.push((localReference * math_lib_1.WAD) / reference);
++i;
}
ratios.push(vaultRatios);
}
const ratioedUserBalances = userBalances.flatMap((uB, i) => uB.map((b, j) => (b * math_lib_1.WAD) / ratios[i][j]));
const ratioedUserInputs = userInputs.flatMap((uI, i) => uI.map((I, j) => (I * math_lib_1.WAD) / ratios[i][j]));
let smallestUserBalance = ratioedUserBalances[0];
let smallestUserBalanceIndex = 0;
for (let i = 1; i < ratioedUserBalances.length; ++i) {
const userBalanceCompare = ratioedUserBalances[i];
if (userBalanceCompare === 0n) {
continue;
}
if (userBalanceCompare < smallestUserBalance) {
smallestUserBalance = userBalanceCompare;
smallestUserBalanceIndex = i;
}
}
let largestUserInput = ratioedUserInputs[0];
for (let i = 1; i < ratioedUserInputs.length; ++i) {
const userInputCompare = ratioedUserInputs[i];
if (userInputCompare > largestUserInput) {
largestUserInput = userInputCompare;
}
}
const referenceBalance = smallestUserBalance > largestUserInput
? largestUserInput
: smallestUserBalance;
const searchForSubIndex = (relevantIndex) => {
let n = relevantIndex;
let i = 0;
for (; i < userInputs.length; ++i) {
const subElementLength = userInputs[i].length;
if (n >= subElementLength) {
n = n - subElementLength;
continue;
}
if (n < subElementLength) {
break;
}
}
return [i, n];
};
const restrictingBalanceIndex = smallestUserBalance > largestUserInput
? [-1, -1]
: searchForSubIndex(smallestUserBalanceIndex);
const ignoreIndexes = ratioedUserBalances.map((v) => v === 0n);
const newUserInputs = [];
for (let i = 0; i < ratios.length; ++i) {
const vaultRatios = ratios[i];
const newUserVaultInput = [];
for (let j = 0; j < vaultRatios.length; ++j) {
const ratio = vaultRatios[j];
if (ignoreIndexes[i][j]) {
newUserVaultInput.push(0n);
}
else {
newUserVaultInput.push((referenceBalance * ratio) / math_lib_1.WAD);
}
}
newUserInputs.push(newUserVaultInput);
}
return { newUserInputs, restrictingBalanceIndex };
}
function balancedWithdrawalMacro(vaults, userVaultTokens, userInput) {
const numTargetPoolTokens = solvWithdrawEqual(vaults[userInput.vaultIndex], userInput.value, userInput.tokenIndex);
const vaultTokenPercentage = (numTargetPoolTokens * math_lib_1.WAD) / userVaultTokens[userInput.vaultIndex];
const vaultTokensToWithdraw = userVaultTokens.map((v) => (v * vaultTokenPercentage) / math_lib_1.WAD);
const newUserInputs = vaults.map((vault, index) => withdrawEqual(vault, vaultTokensToWithdraw[index]));
return {
newUserInputs,
vaultTokensToWithdraw,
};
}
function findOptimalWithdrawLiquiditySwaps(vaults, userVaultTokens, userWithdrawals) {
const boughtUnits = vaults[0].amplification === math_lib_1.WAD
? (0, liquidity_volatile_functions_1.assetsForUnitsVolatile)(vaults, userWithdrawals)
: (0, liquidity_amplified_functions_1.assetsForUnitsAmplified)(vaults, userWithdrawals);
const holdingUnits = vaults[0].amplification === math_lib_1.WAD
? (0, liquidity_volatile_functions_1.poolTokensToUnitsVolatile)(vaults, userVaultTokens)
: (0, liquidity_amplified_functions_1.poolTokensToUnitsAmplified)(vaults, userVaultTokens);
const unitSwaps = vaults[0].amplification === math_lib_1.WAD
? (0, liquidity_volatile_functions_1.findOptimalWithdrawalsVolatile)(vaults, boughtUnits
.flatMap((unitArray) => (0, math_utils_1.bigNumberSum)(unitArray))
.map((U) => U * -1n), holdingUnits)
: (0, liquidity_amplified_functions_1.findOptimalWithdrawalsAmplified)(vaults, boughtUnits
.flatMap((unitArray) => (0, math_utils_1.bigNumberSum)(unitArray))
.map((U) => U * -1n), holdingUnits);
const vaultTokenSwaps = unitSwaps.map((swap) => {
const U = swap.units;
const fromVault = vaults[swap.from];
const vaultTokens = fromVault.amplification === math_lib_1.WAD
? (0, math_volatile_integrals_1.calcUnitsForVaultTokensVol)(U, fromVault.totalSupply, (0, math_utils_1.bigNumberSum)(fromVault.weights))
: (0, math_amplified_integrals_1.calcUnitsForVaultTokensAmp)(U, fromVault.totalSupply, fromVault.balances, fromVault.weights, fromVault.unitTracker, fromVault.amplification);
const userVaultToken = userVaultTokens[swap.from];
return {
...swap,
vaultTokens: vaultTokens < userVaultToken ? vaultTokens : vaultTokens,
};
});
return { vaultTokenSwaps, boughtUnits };
}
function distributeVaultTokenValue(vaults, userVaultTokens, withdrawalWeights) {
const holdingUnits = vaults[0].amplification === math_lib_1.WAD
? (0, liquidity_volatile_functions_1.poolTokensToUnitsVolatile)(vaults, userVaultTokens)
: (0, liquidity_amplified_functions_1.poolTokensToUnitsAmplified)(vaults, userVaultTokens);
const totalHoldingUnits = (0, math_utils_1.bigNumberSum)(holdingUnits);
const assetWeightTotal = (0, math_utils_1.bigNumberSum)(withdrawalWeights.flatMap((vaultWithdrawalWeights) => vaultWithdrawalWeights.map((v) => v)));
const withdrawableTokens = [];
for (let vaultIndex = 0; vaultIndex < vaults.length; ++vaultIndex) {
const vault = vaults[vaultIndex];
const vaultWithdrawalWeights = withdrawalWeights[vaultIndex];
const withdrawableTokensForVault = [];
for (let assetIndex = 0; assetIndex < vaultWithdrawalWeights.length; ++assetIndex) {
const weightedWithdrawalAsset = vaultWithdrawalWeights[assetIndex];
const unitForAsset = (weightedWithdrawalAsset * totalHoldingUnits) / assetWeightTotal;
const assetBalance = vault.balances[assetIndex];
const assetWeight = vault.weights[assetIndex];
const amplification = vault.amplification;
withdrawableTokensForVault.push(amplification === math_lib_1.WAD
? (0, math_volatile_functions_1.receiveAssetVol)(assetBalance, unitForAsset, assetWeight)
: (0, math_amplified_functions_1.receiveAssetAmp)(assetBalance, unitForAsset, assetWeight, amplification));
}
withdrawableTokens.push(withdrawableTokensForVault);
}
return withdrawableTokens;
}
function computeEstimatedOutGivenPercentageWithdrawal(vaults, userPoolTokens, percentage, vaultIndex, tokenIndex) {
const modifiedPoolTokens = userPoolTokens.map((upt) => (upt * percentage) / math_lib_1.WAD);
const toWithdrawUnits = vaults[0].amplification === math_lib_1.WAD
? (0, liquidity_volatile_functions_1.poolTokensToUnitsVolatile)(vaults, modifiedPoolTokens)
: (0, liquidity_amplified_functions_1.poolTokensToUnitsAmplified)(vaults, modifiedPoolTokens);
const toVault = vaults[vaultIndex];
const toBalance = toVault.balances[tokenIndex];
const toWeight = toVault.weights[tokenIndex];
const amp = toVault.amplification;
const tokenOut = amp === math_lib_1.WAD
? (0, math_volatile_functions_1.receiveAssetVol)(toBalance, (0, math_utils_1.bigNumberSum)(toWithdrawUnits), toWeight)
: (0, math_amplified_functions_1.receiveAssetAmp)(toBalance, (0, math_utils_1.bigNumberSum)(toWithdrawUnits), toWeight, amp);
const _vaultTokenOut = amp === math_lib_1.WAD
? (0, math_volatile_integrals_1.calcUnitsToVaultTokensVol)((0, math_utils_1.bigNumberSum)(toWithdrawUnits), toVault.totalSupply, (0, math_utils_1.bigNumberSum)(toVault.weights))
: (0, math_amplified_integrals_1.calcUnitsToVaultTokensAmp)((0, math_utils_1.bigNumberSum)(toWithdrawUnits), toVault.totalSupply, toVault.balances, toVault.weights, toVault.unitTracker, toVault.amplification);
return tokenOut;
}
function findMeExpectedWithdrawnUnits(vaults, userVaultTokens, percentage, vaultIndex) {
const modifiedPoolTokens = userVaultTokens.map((upt) => (upt * percentage) / math_lib_1.WAD);
const valueOfWantToWithdrawTokens = vaults[0].amplification === math_lib_1.WAD
? (0, liquidity_volatile_functions_1.poolTokensToUnitsVolatile)(vaults, modifiedPoolTokens)
: (0, liquidity_amplified_functions_1.poolTokensToUnitsAmplified)(vaults, modifiedPoolTokens);
const toWithdrawUnits = vaults.map((_) => 0n);
toWithdrawUnits[vaultIndex] = (0, math_utils_1.bigNumberSum)(valueOfWantToWithdrawTokens);
const holdingUnits = vaults[0].amplification === math_lib_1.WAD
? (0, liquidity_volatile_functions_1.poolTokensToUnitsVolatile)(vaults, userVaultTokens)
: (0, liquidity_amplified_functions_1.poolTokensToUnitsAmplified)(vaults, userVaultTokens);
const unitSwaps = vaults[0].amplification === math_lib_1.WAD
? (0, liquidity_volatile_functions_1.findOptimalWithdrawalsVolatile)(vaults, toWithdrawUnits.map((U) => U * -1n), holdingUnits)
: (0, liquidity_amplified_functions_1.findOptimalWithdrawalsAmplified)(vaults, toWithdrawUnits.map((U) => U * -1n), holdingUnits);
const vaultTokenSwaps = unitSwaps.map((swap) => {
const U = swap.units;
const fromVault = vaults[swap.from];
const vaultTokens = fromVault.amplification === math_lib_1.WAD
? (0, math_volatile_integrals_1.calcUnitsForVaultTokensVol)(U, fromVault.totalSupply, (0, math_utils_1.bigNumberSum)(fromVault.weights))
: (0, math_amplified_integrals_1.calcUnitsForVaultTokensAmp)(U, fromVault.totalSupply, fromVault.balances, fromVault.weights, fromVault.unitTracker, fromVault.amplification);
const userVaultToken = userVaultTokens[swap.from];
return {
...swap,
vaultTokens: vaultTokens < userVaultToken ? vaultTokens : vaultTokens,
};
});
return { vaultTokenSwaps };
}
//# sourceMappingURL=math.functions.js.map