Skip to content

Instantly share code, notes, and snippets.

@earthchie
Created May 13, 2021 15:12
Show Gist options
  • Save earthchie/b8dc9f8cbbf842ee1975938845d96bc2 to your computer and use it in GitHub Desktop.
Save earthchie/b8dc9f8cbbf842ee1975938845d96bc2 to your computer and use it in GitHub Desktop.
Simple API to get a exchange rate from PancakeSwap V2 Router
const express = require('express');
const { ethers } = require('ethers');
const app = express();
const port = 3000;
const provider = new ethers.providers.JsonRpcProvider('https://bsc-dataseed.binance.org/');
const contract = {
factory: '0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73', // PancakeSwap V2 factory
router: '0x10ED43C718714eb63d5aA57B78B54704E256024E', // PancakeSwap V2 router
};
const tokens = {
BUSD: '0xe9e7cea3dedca5984780bafc599bd69add087d56',
SCZ: '0x39f1014a88c8ec087cedf1bfc7064d24f507b894',
DOP: '0x844fa82f1e54824655470970f7004dd90546bb28',
};
const router = new ethers.Contract(
contract.router,
['function getAmountsOut(uint amountIn, address[] memory path) public view returns (uint[] memory amounts)'],
provider
);
app.get('/getPrice', (req, res) => {
let token = req.query.token;
if(token.indexOf('0x') === -1){
token = tokens[token.toUpperCase()];
}
if(token) {
getPrice(token, tokens.BUSD).then(price => {
res.json({
success: true,
BUSD: price
});
});
}else{
res.status(400).json({
success: false,
description: 'missing `token` parameter'
});
}
});
app.listen(port, () => {
console.log(`getPrice listening at http://localhost:${port}`)
});
async function getPrice(inputCurrency, outputCurrency){
const amounts = await router.getAmountsOut(ethers.utils.parseUnits('1', 18), [inputCurrency, outputCurrency]);
return amounts[1].toString()/1e18;
}
@axssbug
Copy link

axssbug commented Aug 15, 2021

it's incorrect the first argument of getAmountsOut, must div the token decimal not 18

@thanhvt
Copy link

thanhvt commented Sep 3, 2021

Can I check price real time. I feel it incorrect

@grallc
Copy link

grallc commented Oct 26, 2021

Doesn't seem to be realtime, but thanks!

@mtl1979
Copy link

mtl1979 commented Jun 2, 2022

First parameter to getAmountsOut() should be 1 to avoid underflow when token has less than 18 decimals... If for example the token has 2 decimals, the divisor must be 1e16 to get correct result. Basically divisor is 10^(18-decimals). For some tokens it is also required to use for example "WBNB" as output currency as there is no "BUSD" pair yet. Then to get price as "BUSD", input currency must be "WBNB" and output currency must be "BUSD". That doesn't need divisor at all, just multiply with the price from first step.

@earthchie
Copy link
Author

First parameter to getAmountsOut() should be 1 to avoid underflow when token has less than 18 decimals... If for example the token has 2 decimals, the divisor must be 1e16 to get correct result. Basically divisor is 10^(18-decimals). For some tokens it is also required to use for example "WBNB" as output currency as there is no "BUSD" pair yet. Then to get price as "BUSD", input currency must be "WBNB" and output currency must be "BUSD". That doesn't need divisor at all, just multiply with the price from first step.

Wow thanks!

By the way, please also check this gist.
https://gist.github.com/earthchie/bc528f3bcbc1ef00b43c40ab9238cbd2

It is an another implementation to get price and more accurate than this gist.

@mtl1979
Copy link

mtl1979 commented Jun 3, 2022

I already noticed this one gives slightly different results as shown in the liquidity pool... But liquidity pool also includes the accumulated transaction fees debited to liquidity provider.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment