Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ethers and UniswapV2 #17

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
RPC_URL="https://ropsten.infura.io/v3/YOUR_API_KEY"
PRIVATE_KEY="0x..."
ACCOUNT="0x..."
UNISWAPV2_ROUTER_ADDRESS = "0x..."
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ npm_modules
npm_modules/*
node_modules
node_modules/*
.env
*.env
logs/*
logs
examples/*
examples
build
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Price Bot
This is a simple example of a price bot.

## Requirements
- Node 10.x

## Installation
```
# create a .env file
cp .env.example .env

# Fill in the blanks
nano .env

# Install dependencies
npm i

```

## Web3 with UniswapV1 and Kyber

Run the command below to use web3 to connect to uniswapV1 and Kyber to get prices.
Note that uniswapv1 is no longer under active development, but that doesn't mean there aren't arb opps.

```
node index.js
```

## Ethers with UniswapV2 and Kyber

Run the command below to use ethers to connect to uniswapV2 and Kyber to get prices.

```
node index2.js
```
128 changes: 128 additions & 0 deletions index2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
require('dotenv').config()

//http dependencies
const express = require('express')
const bodyParser = require('body-parser')
const http = require('http')
const moment = require('moment-timezone')
const numeral = require('numeral')
const _ = require('lodash')
const axios = require('axios')

// ethereum dependencies
const ethers = require('ethers');
const { parseUnits, formatUnits } = ethers.utils;
const { legos } = require('@studydefi/money-legos');

// SERVER CONFIG
const PORT = process.env.PORT || 5000
const app = express();
const server = http.createServer(app).listen(PORT, () => console.log(`Listening on ${ PORT }`))

// ETHERS CONFIG
const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL);

// Contracts
const uniswapV2 = new ethers.Contract(
process.env.UNISWAPV2_ROUTER_ADDRESS,
[
'function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts)',
'function WETH() external pure returns (address)'
],
provider
);

const kyber = new ethers.Contract(legos.kyber.network.address,
legos.kyber.network.abi,
provider);


async function checkPair(args) {
const { inputTokenSymbol, inputTokenAddress, outputTokenSymbol, outputTokenAddress, inputAmount } = args


// calculate uniswap amount
const path = [inputTokenAddress, outputTokenAddress];
const amounts = await uniswapV2.getAmountsOut(inputAmount, path);
const uniswapAmount = amounts[1];

// calculate kyber amount
const { expectedRate, slippageRate } = await kyber.getExpectedRate(inputTokenAddress, outputTokenAddress, inputAmount);
const kyberExpectedAmount = expectedRate;
const kyberSlippageAmount = slippageRate;



console.table([{
'Input Token': inputTokenSymbol,
'Output Token': outputTokenSymbol,
'Input Amount': formatUnits(inputAmount, 18),
'Uniswap Return': formatUnits(uniswapAmount, 18),
'Kyber Expected Rate': formatUnits(kyberExpectedAmount, 18),
'Kyber Min Return': formatUnits(kyberSlippageAmount, 18),
'Timestamp': moment().tz('America/Chicago').format(),
}])
}

let priceMonitor
let monitoringPrice = false

async function monitorPrice() {
if(monitoringPrice) {
return
}

console.log("Checking prices...")
monitoringPrice = true

try {

// ADD YOUR CUSTOM TOKEN PAIRS HERE!!!

const WETH_ADDRESS = await uniswapV2.WETH(); // Uniswap V2 uses wrapped eth

await checkPair({
inputTokenSymbol: 'WETH',
inputTokenAddress: WETH_ADDRESS,
outputTokenSymbol: 'BAT',
outputTokenAddress: legos.erc20.bat.address,
inputAmount: parseUnits('1', 18)
})

await checkPair({
inputTokenSymbol: 'WETH',
inputTokenAddress: WETH_ADDRESS,
outputTokenSymbol: 'DAI',
outputTokenAddress: '0x6b175474e89094c44da98b954eedeac495271d0f',
inputAmount: parseUnits('1', 18)
})

await checkPair({
inputTokenSymbol: 'WETH',
inputTokenAddress: WETH_ADDRESS,
outputTokenSymbol: 'KNC',
outputTokenAddress: '0xdd974d5c2e2928dea5f71b9825b8b646686bd200',
inputAmount: parseUnits('1', 18)
})

await checkPair({
inputTokenSymbol: 'WETH',
inputTokenAddress: WETH_ADDRESS,
outputTokenSymbol: 'LINK',
outputTokenAddress: '0x514910771af9ca656af840dff83e8264ecf986ca',
inputAmount: parseUnits('1', 18)
})

} catch (error) {
console.error(error)
monitoringPrice = false
clearInterval(priceMonitor)
return
}

monitoringPrice = false
}

// Check markets every n seconds
const POLLING_INTERVAL = process.env.POLLING_INTERVAL || 3000 // 3 Seconds
priceMonitor = setInterval(async () => { await monitorPrice() }, POLLING_INTERVAL)
95 changes: 95 additions & 0 deletions index3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
require('dotenv').config()

//http dependencies
const express = require('express')
const bodyParser = require('body-parser')
const http = require('http')
const moment = require('moment-timezone')
const numeral = require('numeral')
const _ = require('lodash')
const axios = require('axios')

// ethereum dependencies
const ethers = require('ethers');
const { parseUnits, formatUnits } = ethers.utils;
const { legos } = require('@studydefi/money-legos');

// SERVER CONFIG
const PORT = process.env.PORT || 5000
const app = express();
const server = http.createServer(app).listen(PORT, () => console.log(`Listening on ${ PORT }`))

// ETHERS CONFIG
const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL);

// Contracts
const uniswapV2 = new ethers.Contract(
process.env.PANCAKE_ROUTER_ADDRESS,
[
'function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts)',
'function WETH() external pure returns (address)'
],
provider
);


async function checkPair(args) {
const { inputTokenSymbol, inputTokenAddress, outputTokenSymbol, outputTokenAddress, inputAmount } = args


// calculate uniswap amount
const path = [inputTokenAddress, outputTokenAddress];
const amounts = await uniswapV2.getAmountsOut(inputAmount, path);
const uniswapAmount = amounts[1];




console.table([{
'Input Token': inputTokenSymbol,
'Output Token': outputTokenSymbol,
'Input Amount': formatUnits(inputAmount, 18),
'Uniswap Return': formatUnits(uniswapAmount, 18),
'Timestamp': moment().tz('America/Chicago').format(),
}])
}

let priceMonitor
let monitoringPrice = false

async function monitorPrice() {
if(monitoringPrice) {
return
}

console.log("Checking prices...")
monitoringPrice = true

try {

// ADD YOUR CUSTOM TOKEN PAIRS HERE!!!

const WETH_ADDRESS = await uniswapV2.WETH(); // Uniswap V2 uses wrapped eth

await checkPair({
inputTokenSymbol: 'BNB',
inputTokenAddress: process.env.BNB_ADDRESS,
outputTokenSymbol: 'BUSD',
outputTokenAddress: process.env.BUSD_ADDRESS,
inputAmount: parseUnits('1', 18)
})


} catch (error) {
console.error(error)
monitoringPrice = false
clearInterval(priceMonitor)
return
}

monitoringPrice = false
}

// Check markets every n seconds
const POLLING_INTERVAL = process.env.POLLING_INTERVAL || 3000 // 3 Seconds
priceMonitor = setInterval(async () => { await monitorPrice() }, POLLING_INTERVAL)
Loading