As the showcase above, token2:0 is DOT and vtoken2:0 is vDOT on Bifrost Polkadot, getCurrencyAmountByVCurrencyAmount is to input vDOT amount (with decimals) to query the exchange price in DOT.
Bifrost Runtime API (Get vToken Price from Stable Swap)
Bifrost Runtime API (Get vToken Price from Stable Swap)
_calcOutGivenIn/_calcInGivenOut is the method we use to query vToken prices from the Stable Pool, querying the price from DOT/vDOT stable pool as shown in the example below:
// Computes how many tokens can be taken out of a pool if `tokenAmountIn` are sent, given the current balances.
// The amplification parameter equals: A n^(n-1)
export const _calcOutGivenIn = (
amplificationParameter: BigNumber,
balances: BigNumber[],
tokenIndexIn: number,
tokenIndexOut: number,
tokenAmountIn: BigNumber,
options?: {
swapFeePercentage: BigNumber;
tokenInDecimals: number;
},
): BigNumber => {
/**************************************************************************************************************
// outGivenIn token x for y - polynomial equation to solve //
// ay = amount out to calculate //
// by = balance token out //
// y = by - ay (finalBalanceOut) //
// D = invariant D D^(n+1) //
// A = amplification coefficient y^2 + ( S - ---------- - D) * y - ------------- = 0 //
// n = number of tokens (A * n^n) A * n^2n * P //
// S = sum of final balances but y //
// P = product of final balances but y //
**************************************************************************************************************/
// Amount out, so we round down overall.
if (options) {
// Fees are subtracted before scaling
const scalingFactor = 18 - options.tokenInDecimals;
const scaledAmountIn = scale(tokenAmountIn, -scalingFactor);
const scaledAmountInWithoutFees = fp.sub(
scaledAmountIn,
fp.mulUp(scaledAmountIn, options.swapFeePercentage),
);
tokenAmountIn = scale(scaledAmountInWithoutFees, scalingFactor);
}
// Given that we need to have a greater final balance out, the invariant needs to be rounded up
const invariant = _calculateInvariant(amplificationParameter, balances, true);
balances[tokenIndexIn] = fp.add(balances[tokenIndexIn], tokenAmountIn);
const finalBalanceOut = _getTokenBalanceGivenInvariantAndAllOtherBalances(
amplificationParameter,
balances,
invariant,
tokenIndexOut,
);
balances[tokenIndexIn] = fp.sub(balances[tokenIndexIn], tokenAmountIn);
return fp.sub(fp.sub(balances[tokenIndexOut], finalBalanceOut), math.ONE);
};
// Computes how many tokens must be sent to a pool if `tokenAmountOut` are sent given the
// current balances, using the Newton-Raphson approximation.
// The amplification parameter equals: A n^(n-1)
export const _calcInGivenOut = (
amplificationParameter: BigNumber,
balances: BigNumber[],
tokenIndexIn: number,
tokenIndexOut: number,
tokenAmountOut: BigNumber,
options?: {
swapFeePercentage: BigNumber;
tokenInDecimals: number;
},
): BigNumber => {
/**************************************************************************************************************
// inGivenOut token x for y - polynomial equation to solve //
// ax = amount in to calculate //
// bx = balance token in //
// x = bx + ax (finalBalanceIn) //
// D = invariant D D^(n+1) //
// A = amplification coefficient x^2 + ( S - ---------- - D) * x - ------------- = 0 //
// n = number of tokens (A * n^n) A * n^2n * P //
// S = sum of final balances but x //
// P = product of final balances but x //
**************************************************************************************************************/
// Amount in, so we round up overall.
// Given that we need to have a greater final balance in, the invariant needs to be rounded up
const invariant = _calculateInvariant(amplificationParameter, balances, true);
balances[tokenIndexOut] = fp.sub(balances[tokenIndexOut], tokenAmountOut);
const finalBalanceIn = _getTokenBalanceGivenInvariantAndAllOtherBalances(
amplificationParameter,
balances,
invariant,
tokenIndexIn,
);
balances[tokenIndexOut] = fp.add(balances[tokenIndexOut], tokenAmountOut);
let amountIn = fp.add(
fp.sub(finalBalanceIn, balances[tokenIndexIn]),
math.ONE,
);
if (options) {
// Fees are added after scaling
const scalingFactor = 18 - options.tokenInDecimals;
const scaledAmountIn = scale(amountIn, -scalingFactor);
const scaledAmountInWithFees = fp.divUp(
scaledAmountIn,
fp.sub(fp.ONE, options.swapFeePercentage),
);
amountIn = scale(scaledAmountInWithFees, scalingFactor);
}
return amountIn;
};
EVM contract on Moonbeam
Query the exchange rate from SLPx contract on Moonbeam: