Skip to content

Commit

Permalink
Updated documentation and customizability of exchages
Browse files Browse the repository at this point in the history
Apologies as documentation did not mention anything about database migrations.

Also added a check to see if database is connected. If connections fails, suggestions will be outputted.

You can now disable exchanges if exchanges if you don't want data from them. This is still a work in progress, and the implementation isn't the cleanest but it works.

Ideally I would want to ignore if an exchange is unable to get data for a certain cryptocurrency. Any help would be appreciated.
  • Loading branch information
uzillion committed May 17, 2020
1 parent 608ccff commit 616bbe7
Show file tree
Hide file tree
Showing 7 changed files with 591 additions and 2,802 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ You might notice I haven't used any of the exchanges' respective node modules in
echo "DATABASE_URL=$USER@localhost:5432/<db-name>" >> .env
```
+ There is another optional environment variable for directing alerts to a test chat for development and testing purposes. If you want to do so, add the following on a new line to the ".env" file: `TESTING=true`
7. Run `npm install`, and run the app via `npm run start`.
7. Run `npm install`, and run the app via `npm run start`.
**Notes**:
* If you get Database errors, try running `npm run db:migrate`. **IMPORTANT**: This command deletes and recreates all tables. Run this only the first time.
* A lot of the major hosting services come preinstalled with PostgreSQL or provide some plugin. Therefore the steps for creating and setting up the database may differ. For example, [Heroku](https://www.heroku.com/) has an excellend PostgreSQL plugin which upon installation automatically adds the environment variable for the database URL.
* On your local machine, the app will be served on port 3000 of localhost.
Expand Down
161 changes: 85 additions & 76 deletions bin/www
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@ const WebSocket = require('ws');
const trade = require('../lib/trades');
const wall = require('../lib/orders');
const {getPairs} = require('../lib/pairs');
const exchanges = require('../config.js').exchanges;


// ========================================== WebSockets ========================================
let sockets = {
bitfinex: new WebSocket('wss://api.bitfinex.com/ws/2'),
gdax: new WebSocket('wss://ws-feed.gdax.com')
}
let sockets = {}

const buildBinanceSocket = () => {
let stream = "";
Expand All @@ -31,90 +29,101 @@ const buildBinanceSocket = () => {
});
return stream;
}
sockets.binance = new WebSocket('wss://stream.binance.com:9443/stream?streams='+ buildBinanceSocket());



// sockets.binance.close();
// sockets.bitfinex.close();
// soclets.gdax.close();

const refreshStream = () => {
sockets.binance = new WebSocket('wss://stream.binance.com:9443/stream?streams='+ buildBinanceSocket());
}

// Binance API documentation says the streams expire after 24 hours.
// Re-subscribing to the stream after 20 hours
setInterval(refreshStream, 72000000);

sockets.binance.on('message', function(data) {
let obj = JSON.parse(data).data;
if(obj.e == "aggTrade")
trade.binance(obj);
else if(obj.e == "depthUpdate")
wall.binance(obj);
});

sockets.bitfinex.on('open', () => {
const symbols = getPairs();

let request_object = {
event: "subscribe",
channel: "trades",
symbol: ""
if(exchanges.binance) {
sockets.binance = new WebSocket('wss://stream.binance.com:9443/stream?streams='+ buildBinanceSocket());

const refreshStream = () => {
sockets.binance = new WebSocket('wss://stream.binance.com:9443/stream?streams='+ buildBinanceSocket());
}

symbols.forEach(symbol => {
request_object.symbol = symbol;
sockets.bitfinex.send(JSON.stringify(request_object))

// Binance API documentation says the streams expire after 24 hours.
// Re-subscribing to the stream after 20 hours
setInterval(refreshStream, 72000000);

sockets.binance.on('message', function(data) {
let obj = JSON.parse(data).data;
if(obj.e == "aggTrade")
trade.binance(obj);
else if(obj.e == "depthUpdate")
wall.binance(obj);
});
}

request_object = {
event: "subscribe",
channel: "book",
symbol: "",
prec: "P0", // Aggregation of price levels
freq: "F1", // Frequency of stream: F1 - Every 2 seconds
length: "25"
}
if(exchanges.bitfinex) {
sockets.bitfinex = new WebSocket('wss://api.bitfinex.com/ws/2'),

symbols.forEach(symbol => {
request_object.symbol = symbol;
sockets.bitfinex.send(JSON.stringify(request_object))
sockets.bitfinex.on('open', () => {
const symbols = getPairs();

let request_object = {
event: "subscribe",
channel: "trades",
symbol: ""
}

symbols.forEach(symbol => {
request_object.symbol = symbol;
sockets.bitfinex.send(JSON.stringify(request_object))
});

request_object = {
event: "subscribe",
channel: "book",
symbol: "",
prec: "P0", // Aggregation of price levels
freq: "F1", // Frequency of stream: F1 - Every 2 seconds
length: "25"
}

symbols.forEach(symbol => {
request_object.symbol = symbol;
sockets.bitfinex.send(JSON.stringify(request_object))
});

});

sockets.bitfinex.on('message', (data) => {
let obj = JSON.parse(data);
if(obj.channel == "trades" || obj[2] != undefined)
trade.bitfinex(obj);
else if(obj.event != "info") {
wall.bitfinex(obj);
}
});

});
}

sockets.bitfinex.on('message', (data) => {
let obj = JSON.parse(data);
if(obj.channel == "trades" || obj[2] != undefined)
trade.bitfinex(obj);
else if(obj.event != "info") {
wall.bitfinex(obj);
}
})
if(exchanges.coinbase) {
sockets.coinbase = new WebSocket('wss://ws-feed.pro.coinbase.com')

sockets.gdax.on('open', () => {
sockets.coinbase.on('open', () => {

let request_object = {
"type": "subscribe",
"product_ids": getPairs("gdax"),
"channels": ["matches"]
}

sockets.gdax.send(JSON.stringify(request_object))
let request_object = {
"type": "subscribe",
"product_ids": getPairs("coinbase"),
"channels": ["matches"]
}

sockets.coinbase.send(JSON.stringify(request_object))

request_object.channels = ["level2"];
sockets.coinbase.send(JSON.stringify(request_object))
});

sockets.coinbase.on('message', (data) => {
let obj = JSON.parse(data);
if(obj.type == "last_match" || obj.type == "match")
trade.coinbase(obj);
// else if(obj.type == "l2update")
// wall.coinbase(obj);
})
}

request_object.channels = ["level2"];
sockets.gdax.send(JSON.stringify(request_object))
});

sockets.gdax.on('message', (data) => {
let obj = JSON.parse(data);
if(obj.type == "last_match" || obj.type == "match")
trade.gdax(obj);
// else if(obj.type == "l2update")
// wall.gdax(obj);
})
// sockets.binance.close();
// sockets.bitfinex.close();
// soclets.coinbase.close();

// ========================================== WebSockets ========================================

Expand Down
12 changes: 12 additions & 0 deletions config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ module.exports = {
TESTING: (process.env.TESTING === 'true'), // Ignore, unless you want to send alerts to a seperate channel while testing, set this to true
TEST_CHAT_ID: (process.env.TEST_CHAT_ID?process.env.TEST_CHAT_ID:""), // Used when "TESTING" is set to true.

/**
* These are only names of existing exchanges.
*
* Just adding the name will not add the exchange to the subscriptions.
* If you add an exchange here, you also have to implement it. :)
*/
exchanges: {
"binance": true,
"bitfinex": true,
"coinbase": true
},

currencies: [
"BTCUSD", "ETHUSD", "EOSUSD", "LTCUSD", // USD Comparative (use USD even for USDT)
"ETHBTC", "EOSBTC", "LTCBTC", // BTC Comparative
Expand Down
12 changes: 11 additions & 1 deletion db/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
require('dotenv').config();
const pg = require("pg-promise")();
const db = pg(process.env.DATABASE_URL);
let db;
try {
db = pg(process.env.DATABASE_URL);
console.log('\033[92m\u2713\033[0m DB connected');
} catch {
console.log('\033[91m\u2717\033[0m Could not connect to database.');
console.log('Please make sure you have run \'npm run db:migrate\' first');
console.log('Also, make sure correct environment variables are set.');
process.exit(1);
}

module.exports = db;
8 changes: 4 additions & 4 deletions lib/trades/gdax.js → lib/trades/coibase.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const updateLimits = () => {
});
}

const gdax = (trade) => {
const coinbase = (trade) => {
let isAggregate = false;
let maker_order_id = trade.maker_order_id;
let taker_order_id = trade.taker_order_id;
Expand All @@ -55,13 +55,13 @@ const gdax = (trade) => {
(usdExp.test(base)?1:usd_values[base]);

if(trade_worth > min_worth[currency]) {
let volume = volumes.gdax[symbol];
let volume = volumes.coinbase[symbol];
let messageObj = {
event: "TRADE",
symbol,
quantity,
price,
exchange: "gdax",
exchange: "coinbase",
isAggregate,
taker_order_id,
maker_order_id
Expand All @@ -75,4 +75,4 @@ const gdax = (trade) => {
}
}

module.exports = {gdax, updateLimits};
module.exports = {coinbase, updateLimits};
Loading

0 comments on commit 616bbe7

Please sign in to comment.