@hikaru-fi/swap-router
Version:
Package for calculating optimal path for executing swaps
186 lines (176 loc) • 4.85 kB
JavaScript
const BN = require('bn.js');
const { MathSol } = require('../utils/LogExpMath');
// 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}
*/
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}
*/
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} amount
* @param {BN} fee
* @returns {BN}
*/
function subtractFee(amount, fee) {
const feeAmount = MathSol.mulUpFixed(amount, fee);
return amount.sub(feeAmount);
}
/**
*
* @param {BN} amount
* @param {BN} fee
* @returns {BN}
*/
function addFee(amount, fee) {
return MathSol.divUpFixed(amount, MathSol.complementFixed(fee));
}
/**
*
* @param {BN} amount
* @param {BN} swapLimitCoefficient
* @returns {BN}
*/
function swapLimit(amount, swapLimitCoefficient) {
return MathSol.mulDownFixed(amount, swapLimitCoefficient);
}
// 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}
*/
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}
*/
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)
// )
}
module.exports = {
calcOutGivenIn,
calcInGivenOut,
swapLimit,
_spotPriceAfterSwapExactTokenInForTokenOutBN,
_spotPriceAfterSwapTokenInForExactTokenOutBN
}