Skip to content

Commit

Permalink
Support for hive HF24 (#3)
Browse files Browse the repository at this point in the history
* hive hf24

* remove steem support, switch to nodejs 12

* update readme

* update readme

* add more rpc nodes

* adjust wait delays on error

* cleanup readme
  • Loading branch information
Jolly-Pirate committed Sep 18, 2020
1 parent 329d23e commit 66baa37
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 145 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:10
FROM node:12

RUN apt-get update && apt-get -y install sudo
RUN npm i npm@latest -g
Expand All @@ -11,6 +11,6 @@ USER pricefeed
WORKDIR /home/pricefeed

COPY package*.json ./
RUN npm install
RUN npm install && npm audit fix
#COPY . .
CMD forever --minUptime 1000 --spinSleepTime 10000 -m 10 app/app.js
25 changes: 12 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# HIVE/STEEM Price Feed
A price feed application written in NodeJS for witnesses on the Hive or Steem network.
# HIVE Price Feed
A price feed application written in NodeJS for witnesses on the Hive network.

## Features
- Application resilience with NodeJS restart on crash/exit.
- Automatic RPC switching.
- Volume Weighted Average Price (VWAP) from several cryptocurrency exchanges.
- Supported exchanges: Binance, Bittrex, Huobi, Ionomy, Poloniex, Probit, Upbit.
- Supported exchanges: Binance, Bittrex, Huobi, Ionomy, Probit, Upbit.

# Pre-install (e.g. Ubuntu 16.04)
# Pre-install (e.g. Ubuntu 18.04)
Requires NodeJS >7.6 (for the async functions).
```
sudo apt update
sudo apt install -y curl software-properties-common gnupg build-essential libssl-dev
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt install -y nodejs
sudo npm i npm@latest -g
```
Expand Down Expand Up @@ -53,6 +53,7 @@ chmod 600 app/config.json
Edit the file `app/config.json` accordingly (see the Configuration section below), then start the app with
```
npm install
npm audit fix
npm start
```

Expand All @@ -73,14 +74,12 @@ If you want to terminate the script press `CTRL-c`, then type `exit` to close th
The configuration is located in the file `app/config.json`.

- witness: witness account
- privateActiveKey : private active key of the witness account
- interval : delay between each feed publishing.
- peg : set to true only if you want to adjust your price feed bias.
- peg_multi : if the peg is enabled, then this will change the "quote" to `1 / peg_multi`, e.g. a peg_multi of 2 it will show a 100% bias on the feed.
- testmode : when set to true, the script won't broadcast the price feed to the blockchain, good for testing or checking the price on the different exchanges
- hivechain/steemchain : select which blockchain to broadcast to, by setting only one of those options to `true`
- hiverpc: array of Hive RPC nodes (be careful not to mix RPC's from both blockchains)
- steemrpc: array of Steem RPC nodes (be careful not to mix RPC's from both blockchains)
- privateActiveKey: private active key of the witness account
- interval: delay between each feed publishing.
- peg: set to true only if you want to adjust your price feed bias.
- peg_multi: if the peg is enabled, then this will change the "quote" to `1 / peg_multi`, e.g. a peg_multi of 2 it will show a 100% bias on the feed.
- testmode: when set to true, the script won't broadcast the price feed to the blockchain, good for testing or checking the price on the different exchanges
- hiverpc: array of Hive RPC nodes

The different exchanges can be enabled/disabled with `true` or `false`. Always keep an eye on the exchange prices/volumes and edit their setting accordingly, then restart the price feed.

Expand Down
143 changes: 50 additions & 93 deletions app/app.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
console.log('NodeJS', process.version);

const
steem = require("steem"),
hive = require("@hiveio/hive-js"),
config = require("./config.json"),
utils = require("./utils.js");

hive.config.set('rebranded_api', 'true');
hive.broadcast.updateOperations(); // Necessary to update the already loaded operations

const
Reset = "\x1b[0m",
Blue = "\x1b[34m",
Expand All @@ -11,18 +16,13 @@ const
Yellow = "\x1b[33m",
Underscore = "\x1b[4m";

if (config.steemchain && config.hivechain) {
console.log("Enable only one blockchain in the app/config.json file, hivechain or steemchain, then restart");
console.log("Exiting");
process.exit();
}

var counter = 0;
utils.switchrpc(counter);

function checkAccount() {
return new Promise((resolve, reject) => {
steem.api.getAccountsAsync([config.witness])
hive.api.getAccountsAsync([config.witness])
.then(function (result) {
if (result[0]) {
var publicKeyFromBlockchain = result[0].active.key_auths[0][0];
Expand All @@ -41,10 +41,11 @@ function checkAccount() {
.catch(function (err) {
console.log(utils.getDate(), Red, "Error in getAccountsAsync()", err, Reset);
if (JSON.stringify(err, null, 1).includes("RPCError: Unable to acquire database lock")) {
utils.wait(2000);
utils.wait(5000);
counter = 0;
checkAccount();
} else {
utils.wait(10000);
utils.switchrpc(counter);
counter++;
checkAccount();
Expand Down Expand Up @@ -76,88 +77,48 @@ async function priceFeed() {
probitUsdtToken, probitPrice, probitVolume,
binanceTokenBtc, binancePrice, binanceVolume,
huobiTokenUsdt, huobiPrice, huobiVolume,
poloniexBtcToken, poloniexPrice, poloniexVolume,
upbitBtcToken, upbitPrice, upbitVolume;

// select blockchain from config
if (config.hivechain) {
token = "HIVE";
if (config.bittrex) {
bittrexUsdtBtc = await utils.getPrice("bittrex", "USDT-BTC");
bittrexBtcToken = await utils.getPrice("bittrex", "BTC-HIVE");
bittrexPrice = bittrexUsdtBtc.price * bittrexBtcToken.price;
bittrexVolume = bittrexBtcToken.volume;
}
if (config.ionomy) {
// Ionomy doesn't have a USDT/BTC pair, so using the average from exchanges
binanceBtcUsdt = await utils.getPrice("binance", "BTCUSDT");
bittrexUsdtBtc = await utils.getPrice("bittrex", "USDT-BTC");
poloniexUsdtBtc = await utils.getPrice("poloniex", "USDT_BTC");
upbitUsdtBtc = await utils.getPrice("upbit", "USDT-BTC");
averageUsdtBtc = (binanceBtcUsdt.price + bittrexUsdtBtc.price + poloniexUsdtBtc.price + upbitUsdtBtc.price) / 4;
ionomyBtcToken = await utils.getPrice("ionomy", "btc-hive");
ionomyPrice = averageUsdtBtc * ionomyBtcToken.price;
ionomyVolume = ionomyBtcToken.volume;
}
if (config.probit) {
probitUsdtToken = await utils.getPrice("probit", "HIVE-USDT");
probitPrice = probitUsdtToken.price;
probitVolume = probitUsdtToken.volume;
}
if (config.huobi) {
huobiTokenUsdt = await utils.getPrice("huobi", "hiveusdt");
huobiPrice = huobiTokenUsdt.price;
huobiVolume = huobiTokenUsdt.volume;
}
}
token = "HIVE";

if (config.steemchain) {
token = "STEEM";
if (config.binance) {
binanceBtcUsdt = await utils.getPrice("binance", "BTCUSDT");
binanceTokenBtc = await utils.getPrice("binance", "STEEMBTC");
binancePrice = binanceTokenBtc.price * binanceBtcUsdt.price;
binanceVolume = binanceTokenBtc.volume;
}
if (config.bittrex) {
bittrexUsdtBtc = await utils.getPrice("bittrex", "USDT-BTC");
bittrexBtcToken = await utils.getPrice("bittrex", "BTC-STEEM");
bittrexPrice = bittrexUsdtBtc.price * bittrexBtcToken.price;
bittrexVolume = bittrexBtcToken.volume;
}
if (config.huobi) {
huobiTokenUsdt = await utils.getPrice("huobi", "hiveusdt");
huobiPrice = huobiTokenUsdt.price;
huobiVolume = huobiTokenUsdt.volume;
}
if (config.ionomy) {
// Ionomy doesn't have a USDT/BTC pair, so using the average from exchanges
binanceBtcUsdt = await utils.getPrice("binance", "BTCUSDT");
bittrexUsdtBtc = await utils.getPrice("bittrex", "USDT-BTC");
poloniexUsdtBtc = await utils.getPrice("poloniex", "USDT_BTC");
upbitUsdtBtc = await utils.getPrice("upbit", "USDT-BTC");
averageUsdtBtc = (binanceBtcUsdt.price + bittrexUsdtBtc.price + poloniexUsdtBtc.price + upbitUsdtBtc.price) / 4;
ionomyBtcToken = await utils.getPrice("ionomy", "btc-steem");
ionomyPrice = averageUsdtBtc * ionomyBtcToken.price;
ionomyVolume = ionomyBtcToken.volume;
}
if (config.poloniex) {
poloniexUsdtBtc = await utils.getPrice("poloniex", "USDT_BTC");
poloniexBtcToken = await utils.getPrice("poloniex", "BTC_STEEM");
poloniexPrice = poloniexUsdtBtc.price * poloniexBtcToken.price;
poloniexVolume = poloniexBtcToken.volume;
}
if (config.probit) {
probitUsdtToken = await utils.getPrice("probit", "STEEM-USDT");
probitPrice = probitUsdtToken.price;
probitVolume = probitUsdtToken.volume;
}
if (config.upbit) {
upbitUsdtBtc = await utils.getPrice("upbit", "USDT-BTC");
upbitBtcToken = await utils.getPrice("upbit", "BTC-STEEM");
upbitPrice = upbitUsdtBtc.price * upbitBtcToken.price;
upbitVolume = upbitBtcToken.volume;
}
if (config.binance) {
binanceBtcUsdt = await utils.getPrice("binance", "BTCUSDT");
binanceTokenBtc = await utils.getPrice("binance", "HIVEBTC");
binancePrice = binanceTokenBtc.price * binanceBtcUsdt.price;
binanceVolume = binanceTokenBtc.volume;
}
if (config.bittrex) {
bittrexUsdtBtc = await utils.getPrice("bittrex", "USDT-BTC");
bittrexBtcToken = await utils.getPrice("bittrex", "BTC-HIVE");
bittrexPrice = bittrexUsdtBtc.price * bittrexBtcToken.price;
bittrexVolume = bittrexBtcToken.volume;
}
if (config.huobi) {
huobiTokenUsdt = await utils.getPrice("huobi", "hiveusdt");
huobiPrice = huobiTokenUsdt.price;
huobiVolume = huobiTokenUsdt.volume;
}
if (config.ionomy) {
// Ionomy doesn't have a USDT/BTC pair, so using the average from exchanges
binanceBtcUsdt = await utils.getPrice("binance", "BTCUSDT");
bittrexUsdtBtc = await utils.getPrice("bittrex", "USDT-BTC");
poloniexUsdtBtc = await utils.getPrice("poloniex", "USDT_BTC");
upbitUsdtBtc = await utils.getPrice("upbit", "USDT-BTC");
averageUsdtBtc = (binanceBtcUsdt.price + bittrexUsdtBtc.price + poloniexUsdtBtc.price + upbitUsdtBtc.price) / 4;
ionomyBtcToken = await utils.getPrice("ionomy", "btc-hive");
ionomyPrice = averageUsdtBtc * ionomyBtcToken.price;
ionomyVolume = ionomyBtcToken.volume;
}
if (config.probit) {
probitUsdtToken = await utils.getPrice("probit", "HIVE-USDT");
probitPrice = probitUsdtToken.price;
probitVolume = probitUsdtToken.volume;
}
if (config.upbit) {
upbitUsdtBtc = await utils.getPrice("upbit", "USDT-BTC");
upbitBtcToken = await utils.getPrice("upbit", "BTC-HIVE");
upbitPrice = upbitUsdtBtc.price * upbitBtcToken.price;
upbitVolume = upbitBtcToken.volume;
}

var priceArray = [];
Expand All @@ -180,10 +141,6 @@ async function priceFeed() {
console.log(("Ionomy").padEnd(8), "$" + ionomyPrice.toFixed(3), Math.floor(ionomyVolume).toLocaleString().padStart(10));
priceArray.push([ionomyPrice, ionomyVolume]);
}
if (poloniexPrice > 0) {
console.log(("Poloniex").padEnd(8), "$" + poloniexPrice.toFixed(3), Math.floor(poloniexVolume).toLocaleString().padStart(10));
priceArray.push([poloniexPrice, poloniexVolume]);
}
if (probitPrice > 0) {
console.log(("Probit").padEnd(8), "$" + probitPrice.toFixed(3), Math.floor(probitVolume).toLocaleString().padStart(10));
priceArray.push([probitPrice, probitVolume]);
Expand Down Expand Up @@ -268,7 +225,7 @@ async function priceFeed() {
console.log("Price after the peg bias : ", (adjustedVWAP / quote).toFixed(3));
}

var exchangeRate = {base: base, quote: quote + " STEEM"};
var exchangeRate = {base: base, quote: quote + " HIVE"};

if (Number(adjustedVWAP) === 0)
console.log(Red + "PROBLEM WITH VWAP" + Reset);
Expand All @@ -277,7 +234,7 @@ async function priceFeed() {
console.log(Red + "TEST MODE ON, NOTHING IS BROADCAST" + Reset);

if (!config.testmode && Number(adjustedVWAP) > 0) {
steem.broadcast.feedPublishAsync(config.privateActiveKey, config.witness, exchangeRate)
hive.broadcast.feedPublishAsync(config.privateActiveKey, config.witness, exchangeRate)
.then(function (data) {
if (data)
console.log(Green + utils.getDate(), "Published price feed " + token + "/USD $" + adjustedVWAP + Reset);
Expand Down
22 changes: 12 additions & 10 deletions app/config.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,27 @@

"testmode": false,

"hivechain": true,
"steemchain": false,

"binance": true,
"bittrex": true,
"huobi": true,
"ionomy": true,
"poloniex": true,
"probit": true,
"upbit": true,

"hiverpc": [
"https://anyx.io",
"https://api.hivekings.com",
"https://api.deathwing.me",
"https://api.followbtcnews.com",
"https://api.hive.blog",
"https://api.openhive.network"
],

"steemrpc": [
"https://api.steemit.com"
"https://api.hivekings.com",
"https://api.openhive.network",
"https://api.pharesim.me",
"https://hive.3speak.online",
"https://hive.roelandp.nl",
"https://hived.hive-engine.com",
"https://hived.privex.io",
"https://rpc.ausbit.dev",
"https://rpc.esteem.app",
"https://techcoderx.com"
]
}
26 changes: 12 additions & 14 deletions app/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
const
request = require("request"),
steem = require("steem"),
config = require("./config.json");
hive = require("@hiveio/hive-js"),
config = require("./config.json"),
request = require("request");

hive.config.set('rebranded_api', 'true');
hive.broadcast.updateOperations(); // Necessary to update the already loaded operations

const
Reset = "\x1b[0m",
Expand All @@ -13,7 +16,7 @@ const

var getAccountInfo = function (account) {
return new Promise((resolve, reject) => {
steem.api.getAccounts([account], function (err, response) {
hive.api.getAccounts([account], function (err, response) {
if (err) {
console.log(err);
reject(err);
Expand All @@ -26,7 +29,7 @@ var getAccountInfo = function (account) {
function checkPrivateKey(privateKeyFromConfig, publicKeyFromBlockchain) {
// Verify the private key in the config vs the public key on the blockchain
try {
if (steem.auth.wifIsValid(privateKeyFromConfig, publicKeyFromBlockchain)) {
if (hive.auth.wifIsValid(privateKeyFromConfig, publicKeyFromBlockchain)) {
return true;
} else {
return false;
Expand All @@ -51,17 +54,12 @@ function wait(ms) {

function switchrpc(counter) {
var rpc = [];
if (config.hivechain)
rpc = config.hiverpc;
if (config.steemchain)
rpc = config.steemrpc;
rpc = config.hiverpc;

var maxrpc = rpc.length;

if (rpc && counter !== maxrpc) {
wait(2000);

steem.api.setOptions({url: rpc[counter], useAppbaseApi: true});
hive.api.setOptions({url: rpc[counter], useAppbaseApi: true});
console.log(getDate(), "Switching to RPC", rpc[counter]);

//process.stderr.write("\x07");// "\007" beep
Expand Down Expand Up @@ -101,12 +99,12 @@ function getPrice(exchange, pair) {
break;
case "probit":
// https://docs-en.probit.com/docs/getting-started
// https://www.probit.com/app/exchange/STEEM-USDT
// https://www.probit.com/app/exchange/HIVE-USDT
url = "https://api.probit.com/api/exchange/v1/ticker?market_ids=" + pair;
break;
case "upbit":
// https://docs.upbit.com/v1.0.7/reference
// https://upbit.com/exchange?code=CRIX.UPBIT.BTC-STEEM
// https://upbit.com/exchange?code=CRIX.UPBIT.BTC-HIVE
url = "https://api.upbit.com/v1/ticker?markets=" + pair;
break;
default:
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "pricefeed",
"version": "1.0.0",
"description": "Steem Price Feed in JS",
"version": "3.0.0",
"description": "Hive Price Feed in JS",
"author": "Jolly-Pirate",
"license": "GPL-3.0",
"main": "app.js",
Expand All @@ -14,8 +14,8 @@
"private": true
},
"dependencies": {
"request": "*",
"steem": "*"
"@hiveio/hive-js": "*",
"request": "*"
},
"devDependencies": {
"eslint": "^6.8.0"
Expand Down

0 comments on commit 66baa37

Please sign in to comment.