diff --git a/src/routes/uniswap.route.js b/src/routes/uniswap.route.js index 992fb6c..129d97d 100644 --- a/src/routes/uniswap.route.js +++ b/src/routes/uniswap.route.js @@ -1,4 +1,3 @@ -import BigNumber from 'bignumber.js'; import { ethers } from 'ethers'; import express from 'express'; @@ -11,7 +10,6 @@ const debug = require('debug')('router') const router = express.Router() const uniswap = new Uniswap(process.env.ETHEREUM_CHAIN) -const denomMultiplier = 1e18 const swapMoreThanMaxPriceError = 'Price too high' const swapLessThanMaxPriceError = 'Price too low' @@ -53,25 +51,27 @@ router.post('/sell-price', async (req, res) => { const paramData = getParamData(req.body) const baseTokenAddress = paramData.base const quoteTokenAddress = paramData.quote + const amount = paramData.amount try { // fetch the optimal pool mix from uniswap - const route = await uniswap.fetch_route( + const { trade, expectedOut} = await uniswap.priceSwapIn( baseTokenAddress, // tokenIn is base asset quoteTokenAddress, // tokenOut is quote asset + amount ) - if (route != null) { + if (trade !== null && expectedOut !== null) { res.status(200).json({ network: uniswap.network, timestamp: initTime, latency: latency(initTime, Date.now()), base: baseTokenAddress, quote: quoteTokenAddress, - amount: parseFloat(paramData.amount), - expectedOut: parseFloat(paramData.amount * route.midPrice.toSignificant(8)), - price: route.midPrice.toSignificant(8), - swaps: route.path, + amount: amount, + expectedOut: expectedOut.toSignificant(8), + price: trade.executionPrice.toSignificant(8), + trade: trade, }) } else { // no pool available res.status(200).json({ @@ -80,6 +80,7 @@ router.post('/sell-price', async (req, res) => { }) } } catch (err) { + debug(err) let reason err.reason ? reason = err.reason : reason = statusMessages.operation_error res.status(500).json({ @@ -103,24 +104,26 @@ router.post('/buy-price', async (req, res) => { const paramData = getParamData(req.body) const baseTokenAddress = paramData.base const quoteTokenAddress = paramData.quote + const amount = paramData.amount try { // fetch the optimal pool mix from uniswap - const route = await uniswap.fetch_route( + const { trade, expectedIn } = await uniswap.priceSwapOut( quoteTokenAddress, // tokenIn is quote asset baseTokenAddress, // tokenOut is base asset + amount ) - if (route != null) { + if (trade !== null && expectedIn !== null) { res.status(200).json({ network: uniswap.network, timestamp: initTime, latency: latency(initTime, Date.now()), base: baseTokenAddress, quote: quoteTokenAddress, - amount: parseFloat(paramData.amount), - expectedIn: parseFloat(paramData.amount * route.midPrice.invert().toSignificant(8)), - price: route.midPrice.invert().toSignificant(8), - swaps: route.path, + amount: amount, + expectedIn: expectedIn.toSignificant(8), + price: trade.executionPrice.invert().toSignificant(8), + trade: trade, }) } else { // no pool available res.status(200).json({ @@ -129,6 +132,7 @@ router.post('/buy-price', async (req, res) => { }) } } catch (err) { + debug(err) let reason err.reason ? reason = err.reason : reason = statusMessages.operation_error res.status(500).json({ @@ -157,7 +161,7 @@ router.post('/sell', async (req, res) => { const wallet = new ethers.Wallet(privateKey, uniswap.provider) const baseTokenAddress = paramData.base const quoteTokenAddress = paramData.quote - const amount = new BigNumber(parseInt(paramData.amount * denomMultiplier)) + const amount = paramData.amount let maxPrice if (paramData.maxPrice) { @@ -168,25 +172,22 @@ router.post('/sell', async (req, res) => { gasPrice = parseFloat(paramData.gasPrice) } - const minAmountOut = maxPrice / amount - debug('minAmountOut', minAmountOut) - try { // fetch the optimal pool mix from uniswap - const route = await uniswap.fetch_route( + const { trade, expectedOut} = await uniswap.priceSwapIn( baseTokenAddress, // tokenIn is base asset quoteTokenAddress, // tokenOut is quote asset + amount ) - const price = route.midPrice.toSignificant(8) + const price = trade.executionPrice.toSignificant(8) debug(`Price: ${price.toString()}`) if (!maxPrice || price >= maxPrice) { // pass swaps to exchange-proxy to complete trade const txObj = await uniswap.swapExactIn( wallet, - route, + trade, baseTokenAddress, - amount, gasPrice, ) @@ -197,8 +198,8 @@ router.post('/sell', async (req, res) => { latency: latency(initTime, Date.now()), base: baseTokenAddress, quote: quoteTokenAddress, - amount: parseFloat(paramData.amount), - expectedOut: parseFloat(paramData.amount * route.midPrice.toSignificant(8)), + amount: amount, + expectedOut: expectedOut.toSignificant(8), price: price, gasUsed: parseInt(txObj.gasUsed), txHash: txObj.transactionHash, @@ -240,7 +241,7 @@ router.post('/buy', async (req, res) => { const wallet = new ethers.Wallet(privateKey, uniswap.provider) const baseTokenAddress = paramData.base const quoteTokenAddress = paramData.quote - const amount = new BigNumber(parseInt(paramData.amount * denomMultiplier)) + const amount = paramData.amount let maxPrice if (paramData.maxPrice) { @@ -253,21 +254,20 @@ router.post('/buy', async (req, res) => { try { // fetch the optimal pool mix from uniswap - const route = await uniswap.fetch_route( + const { trade, expectedIn} = await uniswap.priceSwapOut( quoteTokenAddress, // tokenIn is quote asset baseTokenAddress, // tokenOut is base asset - // amount, + amount, ) - const price = route.midPrice.invert().toSignificant(8) + const price = trade.executionPrice.invert().toSignificant(8) debug(`Price: ${price.toString()}`) if (!maxPrice || price <= maxPrice) { // pass swaps to exchange-proxy to complete trade const txObj = await uniswap.swapExactOut( wallet, - route, + trade, baseTokenAddress, - amount, gasPrice, ) @@ -278,8 +278,8 @@ router.post('/buy', async (req, res) => { latency: latency(initTime, Date.now()), base: baseTokenAddress, quote: quoteTokenAddress, - amount: parseFloat(paramData.amount), - expectedIn: parseFloat(paramData.amount * route.midPrice.invert().toSignificant(8)), + amount: amount, + expectedIn: expectedIn.toSignificant(8), price: price, gasUsed: parseInt(txObj.gasUsed), txHash: txObj.transactionHash, diff --git a/src/services/uniswap.js b/src/services/uniswap.js index 11ebde3..2216074 100644 --- a/src/services/uniswap.js +++ b/src/services/uniswap.js @@ -5,7 +5,7 @@ const debug = require('debug')('router') // constants const ROUTER = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D'; -const GAS_LIMIT = 1200000; +const GAS_LIMIT = 150688; const TTL = 60; export default class Uniswap { @@ -46,12 +46,28 @@ export default class Uniswap { return route } - async swapExactIn (wallet, route, tokenAddress, amountIn, gasPrice) { - const tIn = await uni.Fetcher.fetchTokenData(this.chainID, tokenAddress) - const tokenAmountIn = new uni.TokenAmount(tIn, amountIn) + async priceSwapIn (tokenIn, tokenOut, tokenInAmount) { + const tIn = await uni.Fetcher.fetchTokenData(this.chainID, tokenIn) + const tokenAmountIn = new uni.TokenAmount(tIn, ethers.utils.parseUnits(tokenInAmount, tIn.decimals)) + const route = await this.fetch_route(tokenIn, tokenOut) + const trade = uni.Trade.exactIn(route, tokenAmountIn) + const expectedOut = trade.minimumAmountOut(this.allowedSlippage) + return { trade, expectedOut } + } + + async priceSwapOut (tokenIn, tokenOut, tokenOutAmount) { + const tOut = await uni.Fetcher.fetchTokenData(this.chainID, tokenOut) + const tokenAmountOut = new uni.TokenAmount(tOut, ethers.utils.parseUnits(tokenOutAmount, tOut.decimals)) + const route = await this.fetch_route(tokenIn, tokenOut) + const trade = uni.Trade.exactOut(route, tokenAmountOut) + const expectedIn = trade.maximumAmountIn(this.allowedSlippage) + return { trade, expectedIn } + } + + async swapExactIn (wallet, trade, tokenAddress, gasPrice) { const result = uni.Router.swapCallParameters( - uni.Trade.exactIn(route, tokenAmountIn), - { + trade, + { ttl: TTL, recipient: wallet.address, allowedSlippage: this.allowedSlippage @@ -73,15 +89,13 @@ export default class Uniswap { return txObj } - async swapExactOut (wallet, route, tokenAddress, amountOut, gasPrice) { - const tOut = await uni.Fetcher.fetchTokenData(this.chainID, tokenAddress) - const tokenAmountOut = new uni.TokenAmount(tOut, amountOut) + async swapExactOut (wallet, trade, tokenAddress, gasPrice) { const result = uni.Router.swapCallParameters( - uni.Trade.exactOut(route, tokenAmountOut), - { - ttl: TTL, - recipient: wallet.address, - allowedSlippage: this.allowedSlippage + trade, + { + ttl: TTL, + recipient: wallet.address, + allowedSlippage: this.allowedSlippage } )