@hikaru-fi/sc-calculators
Version:
Package for pool calculations
251 lines (239 loc) • 6.72 kB
JavaScript
import BN from 'bn.js';
import { MathSol } from '../utils/LogExpMath.mjs';
// The following function are BN versions implemented by Sergio.
// BN was requested from integrators as it is more efficient.
// Swap outcomes formulas should match exactly those from smart contracts.
// PairType = 'token->token'
// SwapType = 'swapExactIn'
/**
*
* @param {BN} balanceIn
* @param {BN} weightIn
* @param {BN} balanceOut
* @param {BN} weightOut
* @param {BN} amountIn
* @param {BN} fee
* @returns {BN}
*/
export function calcOutGivenIn(
balanceIn,
weightIn,
balanceOut,
weightOut,
amountIn,
fee
) {
// is it necessary to check ranges of variables? same for the other functions
amountIn = subtractFee(amountIn, fee);
const exponent = MathSol.divDownFixed(weightIn, weightOut);
const denominator = MathSol.add(balanceIn, amountIn);
const base = MathSol.divUpFixed(balanceIn, denominator);
const power = MathSol.powUpFixed(base, exponent);
return MathSol.mulDownFixed(balanceOut, MathSol.complementFixed(power));
}
// PairType = 'token->token'
// SwapType = 'swapExactOut'
/**
*
* @param {BN} balanceIn
* @param {BN} weightIn
* @param {BN} balanceOut
* @param {BN} weightOut
* @param {BN} amountOut
* @param {BN} fee
* @returns {BN}
*/
export function calcInGivenOut(
balanceIn,
weightIn,
balanceOut,
weightOut,
amountOut,
fee
) {
const base = MathSol.divUpFixed(balanceOut, balanceOut.sub(amountOut));
const exponent = MathSol.divUpFixed(weightOut, weightIn);
const power = MathSol.powUpFixed(base, exponent);
const ratio = MathSol.sub(power, MathSol.ONE);
const amountIn = MathSol.mulUpFixed(balanceIn, ratio);
return addFee(amountIn, fee);
}
/**
*
* @param {BN} amountOut
* @param {BN} balance
* @param {BN} weight
* @param {BN} lpTotalSupply
* @param {BN} swapFeePercentage
* @returns {BN}
*/
export function calculateLPAmountForTokenOut(
amountOut,
balance,
weight,
lpTotalSupply,
swapFeePercentage
) {
let denominator = MathSol.mulDownFixed(swapFeePercentage, MathSol.complementFixed(weight));
denominator = MathSol.sub(MathSol.ONE, denominator);
denominator = MathSol.mulDownFixed(balance, denominator);
let fraction = MathSol.divDownFixed(amountOut, denominator);
fraction = MathSol.sub(MathSol.ONE, fraction);
fraction = MathSol.powUpFixed(fraction, weight);
return MathSol.sub(lpTotalSupply, MathSol.mulDownFixed(lpTotalSupply, fraction));
}
/**
*
* @param {BN} amount
* @param {BN} fee
* @returns {BN}
*/
export function subtractFee(amount, fee) {
const feeAmount = MathSol.mulUpFixed(amount, fee);
return amount.sub(feeAmount);
}
/**
*
* @param {BN} amount
* @param {BN} fee
* @returns {BN}
*/
export function addFee(amount, fee) {
return MathSol.divUpFixed(amount, MathSol.complementFixed(fee));
}
/**
*
* @param {BN} amount
* @param {BN} swapLimitCoefficient
* @returns {BN}
*/
export function swapLimit(amount, swapLimitCoefficient) {
return MathSol.mulDownFixed(amount, swapLimitCoefficient);
}
/**
*
* @param {BN} balanceIn
* @param {BN} weightIn
* @param {BN} balanceOut
* @param {BN} weightOut
* @param {BN} swapFee
*/
export function spotPrice(
balanceIn,
weightIn,
balanceOut,
weightOut,
swapFee
) {
const numerator = MathSol.mulUpFixed(balanceIn, weightOut);
let denominator = MathSol.mulUpFixed(balanceOut, weightIn);
denominator = MathSol.mulUpFixed(denominator, MathSol.complementFixed(swapFee));
return MathSol.divDownFixed(numerator, denominator);
}
/**
*
* @param {BN} bn
* @returns {Number}
*/
export function bnToNum(bn) {
return Number(bn.toString(10));
}
/**
*
* @param {BN} balanceIn
* @param {BN} weightIn
* @param {BN} balanceOut
* @param {BN} weightOut
* @param {BN} swapFee
* @returns {Number}
*/
export function spotPriceNumeric(
balanceIn,
weightIn,
balanceOut,
weightOut,
swapFee
) {
return (balanceIn * weightOut) / (balanceOut * weighdIn * (1 - swapFee));
}
// TO DO - Swap old versions of these in Pool for the BN version
// PairType = 'token->token'
// SwapType = 'swapExactIn'
/**
*
* @param {BN} balanceIn
* @param {BN} weightIn
* @param {BN} balanceOut
* @param {BN} weightOut
* @param {BN} amountIn
* @param {BN} fee
* @returns {BN}
*/
export function spotPriceAfterSwapExactTokenInForTokenOutBN(
balanceIn,
weightIn,
balanceOut,
weightOut,
amountIn,
fee
) {
const numerator = MathSol.mulUpFixed(balanceIn, weightOut);
let denominator = MathSol.mulUpFixed(balanceOut, weightIn);
const feeComplement = MathSol.complementFixed(fee);
denominator = MathSol.mulUpFixed(denominator, feeComplement);
const base = MathSol.divUpFixed(
balanceIn,
MathSol.add(MathSol.mulUpFixed(amountIn, feeComplement), balanceIn)
);
const exponent = MathSol.divUpFixed(weightIn.add(weightOut), weightOut);
denominator = MathSol.mulUpFixed(
denominator,
MathSol.powUpFixed(base, exponent)
);
return MathSol.divUpFixed(numerator, denominator);
// -(
// (Bi * wo) /
// (Bo * (-1 + f) * (Bi / (Ai + Bi - Ai * f)) ** ((wi + wo) / wo) * wi)
// )
}
// PairType = 'token->token'
// SwapType = 'swapExactOut'
/**
*
* @param {BN} balanceIn
* @param {BN} weightIn
* @param {BN} balanceOut
* @param {BN} weightOut
* @param {BN} amountOut
* @param {BN} fee
* @returns {BN}
*/
export function spotPriceAfterSwapTokenInForExactTokenOutBN(
balanceIn,
weightIn,
balanceOut,
weightOut,
amountOut,
fee
) {
let numerator = MathSol.mulUpFixed(balanceIn, weightOut);
const feeComplement = MathSol.complementFixed(fee);
const base = MathSol.divUpFixed(
balanceOut,
MathSol.sub(balanceOut, amountOut)
);
const exponent = MathSol.divUpFixed(weightIn.add(weightOut), weightIn);
numerator = MathSol.mulUpFixed(
numerator,
MathSol.powUpFixed(base, exponent)
);
const denominator = MathSol.mulUpFixed(
MathSol.mulUpFixed(balanceOut, weightIn),
feeComplement
);
return MathSol.divUpFixed(numerator, denominator);
// -(
// (Bi * (Bo / (-Ao + Bo)) ** ((wi + wo) / wi) * wo) /
// (Bo * (-1 + f) * wi)
// )
}