diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e9a48aa --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.dockerignore +.git/ +node_modules/ +Dockerfile +docker-compose.yml diff --git a/AppConfig.js b/AppConfig.js index 8fa6a1c..9bebd68 100644 --- a/AppConfig.js +++ b/AppConfig.js @@ -24,7 +24,9 @@ var config = { kraken: { name: 'Kraken', orgUrl: 'https://www.kraken.com/', - url: 'https://api.kraken.com/0/public/Ticker?pair=DASHUSD' + url: 'https://api.kraken.com/0/public/Ticker?pair=DASHUSD', + urlEur: 'https://api.kraken.com/0/public/Ticker?pair=DASHEUR', + urlBTC: 'https://api.kraken.com/0/public/Ticker?pair=DASHXBT' }, poloniex: { name: 'Poloniex', @@ -34,17 +36,20 @@ var config = { bittrex: { name: 'Bittrex', orgUrl: 'https://bittrex.com/', - url: 'https://bittrex.com/api/v1.1/public/getmarketsummary?market=btc-dash' + url: 'https://bittrex.com/api/v1.1/public/getmarketsummary?market=btc-dash', + urlEth: 'https://bittrex.com/api/v1.1/public/getmarketsummary?market=ETH-dash' }, bitfinex: { name: 'Bitfinex', orgUrl: 'https://www.bitfinex.com/', - url: 'https://api.bitfinex.com/v1/pubticker/dshusd' + url: 'https://api.bitfinex.com/v1/pubticker/dshusd', + urlBTC: 'https://api.bitfinex.com/v1/pubticker/dshbtc' }, hitbtc: { name: 'Hitbtc', orgUrl: 'https://hitbtc.com/', - url: 'https://api.hitbtc.com/api/1/public/DASHUSD/ticker' + url: 'https://api.hitbtc.com/api/1/public/DASHUSD/ticker', + urlBTC: 'https://api.hitbtc.com/api/1/public/DASHBTC/ticker' }, bithumb: { name: 'Bithumb', @@ -54,7 +59,8 @@ var config = { livecoin: { name: 'Livecoin', orgUrl: 'https://www.livecoin.net', - url: 'https://api.livecoin.net/exchange/ticker?currencyPair=DASH/USD' + url: 'https://api.livecoin.net/exchange/ticker?currencyPair=DASH/USD', + urlBTC: 'https://api.livecoin.net/exchange/ticker?currencyPair=DASH/BTC', }, exmo: { name: 'Exmo', @@ -64,23 +70,48 @@ var config = { yobit: { name: 'Yobit', orgUrl: 'https://yobit.net/', - url: 'https://yobit.net/api/3/ticker/dash_usd' + url: 'https://yobit.net/api/3/ticker/dash_usd', + urlBTC: 'https://yobit.net/api/3/ticker/dash_btc', + urlRur: 'https://yobit.net/api/3/ticker/dash_rur' }, ccex: { name: 'C-cex', orgUrl: 'https://c-cex.com/', - url: 'https://c-cex.com/t/dash-usd.json' + url: 'https://c-cex.com/t/dash-usd.json', + urlBTC: 'https://c-cex.com/t/dash-btc.json' }, - yahoofinance: { - name: 'Yahoo', - orgUrl: 'https://www.yahoo.com/', - url: 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20(%22KRWUSD%22)&format=json&env=store://datatables.org/alltableswithkeys&callback=' + cexio: { + name: 'Cex.io', + orgUrl: 'https://cex.io/', + url: 'https://cex.io/api/last_price/DASH/USD', + urlBTC: 'https://cex.io/api/last_price/DASH/BTC', + urlEur: 'https://cex.io/api/last_price/DASH/EUR' + }, + binance: { + name: 'Binance', + orgUrl: 'https://www.binance.com/', + url: 'https://api.binance.com/api/v3/ticker/price' + }, + coinroom: { + name: 'Coinroom', + orgUrl: 'https://coinroom.com/', + url: 'https://coinroom.com/api/ticker/DASH/USD' + }, + huobi: { + name: 'Huobi', + orgUrl: 'https://www.huobi.pro/', + url: 'https://api.huobi.pro/market/trade?symbol=dashbtc' + }, + CurrencyConverterApi: { + name: 'CurrencyConverterApi', + orgUrl: 'https://free.currencyconverterapi.com/', + url: 'https://free.currencyconverterapi.com/api/v5/convert?q=KRW_USD&compact=y' } }, budgets: { - dashwhale: { - name: 'DashWhale', - url: 'https://www.dashwhale.org/api/v1/budget' + dashCentral: { + name: 'DashCentral', + url: 'https://www.dashcentral.org/api/v1/budget' } }, masternodes: { @@ -95,7 +126,7 @@ var config = { chain: { insight: { name: 'Insight', - url: 'https://insight.dash.siampm.com/api/blocks', + url: 'https://insight.dashevo.org/insight-api-dash/blocks', maxBlocks: 10 } }, diff --git a/CacheConfig.js b/CacheConfig.js index 1c20e38..e2dcbdf 100644 --- a/CacheConfig.js +++ b/CacheConfig.js @@ -1,11 +1,14 @@ +var memcachedHost = process.env.MEMCACHED_HOST || 'localhost'; +var memcachedPort = process.env.MEMCACHED_PORT || '11211'; + var cacheConfig = { - endpoint: 'localhost:11211', + endpoint: memcachedHost + ':' + memcachedPort, exchange: { key: 'dashapi_exchange', - timeout_seconds: 10 + timeout_seconds: 20 }, budgets: { diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6049d63 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM node:9-alpine +LABEL maintainer="Dash Developers " +LABEL description="Dockerised Dash.org Rate Etc API" + +WORKDIR /app +COPY . /app + +RUN npm i npm@latest -g + +RUN npm install --quiet + +CMD ["/usr/local/bin/node", "Server.js"] diff --git a/Server.js b/Server.js index 940fe1d..ec890fc 100644 --- a/Server.js +++ b/Server.js @@ -91,7 +91,7 @@ global.cacheConnection = Cache.connect(); var server = app.listen(AppConfig.port, function () { - var host = server.address().address; + var host = process.env.BIND_HOST || server.address().address; var port = server.address().port; console.log('dash.org api server listening at http://%s:%s', host, port); -}); \ No newline at end of file +}); diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7ddcd50 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +version: '2' +services: + app: + build: . + restart: always + links: + - memcached + environment: + - BIND_HOST=0.0.0.0 # b/c docker + - MEMCACHED_HOST=memcached + ports: + - 127.0.0.1:9090:9090 + memcached: + image: memcached:alpine + restart: always diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..3da4a6f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,897 @@ +{ + "name": "dash.org-api", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "2.1.18", + "negotiator": "0.6.1" + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "requires": { + "lodash": "4.17.5" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sdk": { + "version": "2.208.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.208.0.tgz", + "integrity": "sha1-+V5EUky2LJpuDvlScCNvxqYheNY=", + "requires": { + "buffer": "4.9.1", + "events": "1.1.1", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.1.0", + "xml2js": "0.4.17", + "xmlbuilder": "4.2.1" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "base64-js": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", + "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.16" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.1" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "1.2.3", + "ieee754": "1.1.8", + "isarray": "1.0.0" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "connection-parse": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/connection-parse/-/connection-parse-0.0.7.tgz", + "integrity": "sha1-GOcxiqsGppkmc3KxDFIm0locmmk=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.1" + } + } + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "express": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "requires": { + "accepts": "1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "1.1.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "2.0.3", + "qs": "6.5.1", + "range-parser": "1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "1.4.0", + "type-is": "1.6.16", + "utils-merge": "1.0.1", + "vary": "1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.4.0", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "hashring": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/hashring/-/hashring-3.2.0.tgz", + "integrity": "sha1-/aTv3oqiLNuX+x0qZeiEAeHBRM4=", + "requires": { + "connection-parse": "0.0.7", + "simple-lru-cache": "0.0.2" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.4.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.1" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jackpot": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/jackpot/-/jackpot-0.0.6.tgz", + "integrity": "sha1-PP8GQoXL9m9OqyWTyQvOgWqCGEk=", + "requires": { + "retry": "0.6.0" + } + }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + }, + "log": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/log/-/log-1.4.0.tgz", + "integrity": "sha1-S6HYkP3iSbAx3KA7w36q8yVlbxw=" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "memcached": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/memcached/-/memcached-2.2.2.tgz", + "integrity": "sha1-aPhsz9hLz5PMJe1G1tf8DHUhydU=", + "requires": { + "hashring": "3.2.0", + "jackpot": "0.0.6" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "proxy-addr": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", + "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.6.0" + } + }, + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + } + }, + "request": { + "version": "2.85.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", + "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "retry": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.6.0.tgz", + "integrity": "sha1-HAEHEyeab9Ho3vKK8MP/GHHKpTc=" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.4.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.16.2" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "simple-lru-cache": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/simple-lru-cache/-/simple-lru-cache-0.0.2.tgz", + "integrity": "sha1-1ZzDoZPBpdAyD4Tucy9uRxPlEd0=" + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.1" + } + }, + "sshpk": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.18" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "xml2js": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz", + "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=", + "requires": { + "sax": "1.2.1", + "xmlbuilder": "4.2.1" + } + }, + "xmlbuilder": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", + "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=", + "requires": { + "lodash": "4.17.5" + } + } + } +} diff --git a/service/BudgetService.js b/service/BudgetService.js index 5cfd958..e46dcd1 100644 --- a/service/BudgetService.js +++ b/service/BudgetService.js @@ -33,8 +33,8 @@ var fetchDashBudgetsData = function(callback){ if ( data === undefined ){ log.debug('Budgets not found in cache.'); - log.debug('Fetching budgets from ' + AppConfig.budgets.dashwhale.name + ' at ' + AppConfig.budgets.dashwhale.url); - fetchBudgetsData(AppConfig.budgets.dashwhale.name, AppConfig.budgets.dashwhale.url,function(err, results){ + log.debug('Fetching budgets from ' + AppConfig.budgets.dashCentral.name + ' at ' + AppConfig.budgets.dashCentral.url); + fetchBudgetsData(AppConfig.budgets.dashCentral.name, AppConfig.budgets.dashCentral.url,function(err, results){ if ( !err ){ Cache.storeBudgetsData(results); } diff --git a/service/ExchangeService.js b/service/ExchangeService.js index a8ea980..31749a9 100644 --- a/service/ExchangeService.js +++ b/service/ExchangeService.js @@ -3,24 +3,41 @@ var Async = require('async'); var AppConfig = require('../AppConfig'); var Cache = require('./CacheRepository'); var Logger = require('log'); -var btcPrice = null; var krwUsd = null; var log = new Logger(AppConfig.logLevel); - +var createErrorExtension = function(message, exchange, errortype){ + var errorObject = new Error(); + errorObject.message = message; + errorObject.exchange = exchange; + errorObject.errorType = errortype; + return errorObject; +} var fetchExchangeData = function(exchange, url, callback){ request.get(url, function (err, response, body) { - if ( !err && response.statusCode == 200 ){ - try { - callback(null, JSON.parse(body)); - }catch (e) { - return callback('ERROR parsing response from ' + exchange + '. Details: ' + e + '\nResponse::' + body); - } - }else if ( err ){ - return callback('ERROR: fetching data from ' + exchange + ' (' + url + ') Details: ' + err + '. BODY=' + body, null); - }else{ - return callback('ERROR: unexpected response code (' + response.statusCode + ') from url=[' + url + '] Details: ' + body); + if ( err ){ + var errorFetching = 'ERROR: fetching data from '; + log.debug(errorFetching + exchange + ' (' + url + ') Details: ' + err + '. BODY=' + body, null); + callback(createErrorExtension(errorFetching, exchange, err), null); + return; + } + if (response.statusCode !== 200){ + var unexpectedError = 'ERROR: unexpected response code '; + log.debug( unexpectedError + '(' + response.statusCode + ') from url=[' + url + '] Details: ' + body ); + callback(createErrorExtension( unexpectedError, url, response.statusCode), null); + return; + } + var data; + try { + data = JSON.parse(body); + }catch (e){ + var parseError = 'ERROR parsing response from '; + log.debug(parseError + exchange + '. Details: ' + e + '\nResponse::' + body); + callback(createErrorExtension(parseError, exchange, e), null); + return; } + callback(null, data); + return }); }; @@ -29,17 +46,22 @@ var fetchFromCoinCap = function(callback){ fetchExchangeData(AppConfig.exchanges.coincap.name, AppConfig.exchanges.coincap.url, function(err, result){ if ( err ){ callback(err); - }else{ - var data = { - exchange: AppConfig.exchanges.coincap.name, - url: AppConfig.exchanges.coincap.orgUrl, - price: result[0].price_usd, - volume: result[0]['24h_volume_usd'], - percent_change: result[0].percent_change_24h, - market_cap: result[0].market_cap_usd - }; - callback(null, data); + return; } + if (result === null) { + callback(null, null); + return + } + var data = { + exchange: AppConfig.exchanges.coincap.name, + url: AppConfig.exchanges.coincap.orgUrl, + price: parseFloat(result[0].price_usd), + volume: parseFloat(result[0]['24h_volume_usd']), + percent_change: parseFloat(result[0].percent_change_24h), + market_cap: parseFloat(result[0].market_cap_usd) + }; + callback(null, data); + return; }); }; @@ -48,13 +70,20 @@ var fetchFromCoinCapBtc = function(callback){ fetchExchangeData(AppConfig.exchanges.coincapbtc.name, AppConfig.exchanges.coincapbtc.url, function(err, result){ if ( err ){ callback(err); - }else{ - btcPrice = result[0].price_usd; - var data ={ - btcPrice: result[0].price_usd - } - callback(null, data); + return; + } + if (result === null) { + callback(null, null); + return; + } + btcPrice = parseFloat(result[0].price_usd); + var data ={ + exchange: AppConfig.exchanges.coincapbtc.name, + url: AppConfig.exchanges.coincapbtc.orgUrl, + btcPrice: btcPrice } + callback(null, data); + return; }); }; @@ -67,41 +96,69 @@ var fetchFromWorldCoinIndex = function(callback){ fetchExchangeData(AppConfig.exchanges.worldcoin.name, url, function(err, result){ if ( err ){ callback(err); - }else{ - var dashResults = result.Markets.find(function (market) { - return market.Name === "Dash"; - }); - if ( dashResults ){ - var data = { - exchange: AppConfig.exchanges.worldcoin.name, - url: AppConfig.exchanges.worldcoin.orgUrl, - price: dashResults.Price_usd, - volume: dashResults.Volume_24h, - percent_change: -1 - }; - callback(null, data); - }else{ - callback('Unable to find the Dash Market data in the response from WorldCoinIndex. Endpoint is [' + url + ']'); - } - + return; + } + if (result === null) { + callback(null, null); + return; } + var dashResults = result.Markets.find(function (market) { + return market.Name === "Dash"; + }); + if ( dashResults ){ + var data = { + exchange: AppConfig.exchanges.worldcoin.name, + url: AppConfig.exchanges.worldcoin.orgUrl, + price: parseFloat(dashResults.Price_usd), + volume: parseFloat(dashResults.Volume_24h), + percent_change: -1 + }; + callback(null, data); + return; + } + callback('Unable to find the Dash Market data in the response from WorldCoinIndex. Endpoint is [' + url + ']'); + return; }); }; var fetchFromKraken = function(callback){ + var data = {}; log.debug('Fetching exchange data from ' + AppConfig.exchanges.kraken.name + ' at ' + AppConfig.exchanges.kraken.url); fetchExchangeData(AppConfig.exchanges.kraken.name, AppConfig.exchanges.kraken.url, function(err, result){ if ( err ){ callback(err); - }else{ - var data = { - exchange: AppConfig.exchanges.kraken.name, - url: AppConfig.exchanges.kraken.orgUrl, - price: result.result.DASHUSD.c[0] - }; - data.volume = result.result.DASHUSD.v[1]*data.price; - callback(null, data); + return; + } + if (result === null) { + callback(null, null); + return; } + data = { + exchange: AppConfig.exchanges.kraken.name, + url: AppConfig.exchanges.kraken.orgUrl, + price: parseFloat(result.result.DASHUSD.c['0']) + }; + data.volume = result.result.DASHUSD.v[1]*data.price; + fetchExchangeData(AppConfig.exchanges.kraken.name, AppConfig.exchanges.kraken.urlEur, function(err, result){ + if ( err ){ + callback(err); + return + } + if (result === null) { + callback(null, null); + return; + } + data['price_eur'] = parseFloat(result.result.DASHEUR.c[0]); + fetchExchangeData(AppConfig.exchanges.kraken.name, AppConfig.exchanges.kraken.urlBTC, function(err, result){ + if ( err ){ + callback(err); + return; + } + data['price_btc'] = parseFloat(result.result.DASHXBT.c[0]); + callback(null, data); + return; + }); + }); }); }; @@ -110,81 +167,157 @@ var fetchFromPoloniex = function(callback){ fetchExchangeData(AppConfig.exchanges.poloniex.name, AppConfig.exchanges.poloniex.url, function(err, result){ if ( err ){ callback(err); - }else{ - var data = { - exchange: AppConfig.exchanges.poloniex.name, - url: AppConfig.exchanges.poloniex.orgUrl, - }; - callback(null, data); + return; + } + if (result === null) { + callback(null, null); + return; } + var data = { + exchange: AppConfig.exchanges.poloniex.name, + url: AppConfig.exchanges.poloniex.orgUrl, + price_btc: parseFloat(result.BTC_DASH.last) + }; + callback(null, data); + return; }); }; var fetchFromBittrex= function(callback){ + var data = {}; log.debug('Fetching exchange data from ' + AppConfig.exchanges.bittrex.name + ' at ' + AppConfig.exchanges.bittrex.url); fetchExchangeData(AppConfig.exchanges.bittrex.name, AppConfig.exchanges.bittrex.url, function(err, result){ if ( err ){ callback(err); - }else{ - var data = { - exchange: AppConfig.exchanges.bittrex.name, - url: AppConfig.exchanges.bittrex.orgUrl, - price: result.result[0].Last*btcPrice - }; - data.volume = result.result[0].Volume*data.price; - callback(null, data); + return; + } + if (result === null) { + callback(null, null); + return; } + data = { + exchange: AppConfig.exchanges.bittrex.name, + url: AppConfig.exchanges.bittrex.orgUrl, + price_btc: parseFloat(result.result[0].Last) + }; + data.volume = result.result[0].Volume*data.price_btc; + //fetching ETH price + fetchExchangeData(AppConfig.exchanges.bittrex.name, AppConfig.exchanges.bittrex.urlEth, function(err, result){ + if ( err ){ + callback(err); + return; + } + if (result === null) { + callback(null, null); + return; + } + data['price_eth'] = parseFloat(result.result[0].Last); + callback(null, data); + return; + }); }); + }; var fetchFromBitfinex = function(callback){ + var data = {}; log.debug('Fetching exchange data from ' + AppConfig.exchanges.bitfinex.name + ' at ' + AppConfig.exchanges.bitfinex.url); fetchExchangeData(AppConfig.exchanges.bitfinex.name, AppConfig.exchanges.bitfinex.url, function(err, result){ if ( err ){ callback(err); - }else{ - var data = { - exchange: AppConfig.exchanges.bitfinex.name, - url: AppConfig.exchanges.bitfinex.orgUrl, - price: result.last_price - }; - data.volume = result.volume*data.price; - callback(null, data); + return; + } + if (result === null) { + callback(null, null); + return; } + data = { + exchange: AppConfig.exchanges.bitfinex.name, + url: AppConfig.exchanges.bitfinex.orgUrl, + price: parseFloat(result.last_price) + }; + data.volume = result.volume*data.price; + //fetching BTC price + fetchExchangeData(AppConfig.exchanges.bitfinex.name, AppConfig.exchanges.bitfinex.urlBTC, function(err, result){ + if ( err ){ + callback(err); + return; + } + if (result === null) { + callback(null, null); + return; + } + data['price_btc'] = parseFloat(result.last_price); + callback(null, data); + return; + }); }); + }; var fetchFromHitbtc= function(callback){ + var data = {}; log.debug('Fetching exchange data from ' + AppConfig.exchanges.hitbtc.name + ' at ' + AppConfig.exchanges.hitbtc.url); fetchExchangeData(AppConfig.exchanges.hitbtc.name, AppConfig.exchanges.hitbtc.url, function(err, result){ if ( err ){ callback(err); - }else{ - var data = { - exchange: AppConfig.exchanges.hitbtc.name, - url: AppConfig.exchanges.hitbtc.orgUrl, - price: result.last, - }; - data.volume = result.volume*data.price; - callback(null, data); + return; } + if (result === null) { + callback(null, null); + return; + } + data = { + exchange: AppConfig.exchanges.hitbtc.name, + url: AppConfig.exchanges.hitbtc.orgUrl, + price: parseFloat(result.last) + }; + data.volume = result.volume*data.price; + //Fetch BTC + fetchExchangeData(AppConfig.exchanges.hitbtc.name, AppConfig.exchanges.hitbtc.urlBTC, function(err, result){ + if ( err ){ + callback(err); + return; + } + data['price_btc'] = parseFloat(result.last); + callback(null, data); + return; + }); }); + }; var fetchFromLivecoin= function(callback){ + var data = {}; log.debug('Fetching exchange data from ' + AppConfig.exchanges.livecoin.name + ' at ' + AppConfig.exchanges.livecoin.url); fetchExchangeData(AppConfig.exchanges.livecoin.name, AppConfig.exchanges.livecoin.url, function(err, result){ if ( err ){ callback(err); - }else{ - var data = { - exchange: AppConfig.exchanges.livecoin.name, - url: AppConfig.exchanges.livecoin.orgUrl, - price: result.last - }; - data.volume = result.volume*data.price; - callback(null, data); + return } + if (result === null) { + callback(null, null); + return; + } + data = { + exchange: AppConfig.exchanges.livecoin.name, + url: AppConfig.exchanges.livecoin.orgUrl, + price: parseFloat(result.last) + }; + data.volume = result.volume*data.price + // Fetching BTC price + fetchExchangeData(AppConfig.exchanges.livecoin.name, AppConfig.exchanges.livecoin.urlBTC, function(err, result){ + if ( err ){ + callback(err); + } + if (result === null) { + callback(null, null); + return; + } + data['price_btc'] = parseFloat(result.last); + callback(null, data); + return; + }); }); }; @@ -193,113 +326,321 @@ var fetchFromExmo= function(callback){ fetchExchangeData(AppConfig.exchanges.exmo.name, AppConfig.exchanges.exmo.url, function(err, result){ if ( err ){ callback(err); - }else{ - var data = { - exchange: AppConfig.exchanges.exmo.name, - url: AppConfig.exchanges.exmo.orgUrl, - price: result.DASH_USD.last_trade, - volume: result.DASH_USD.vol_curr, - }; - callback(null, data); + return } + if (result === null) { + callback(null, null); + return; + } + var data = { + exchange: AppConfig.exchanges.exmo.name, + url: AppConfig.exchanges.exmo.orgUrl, + price: parseFloat(result.DASH_USD.last_trade), + price_btc: parseFloat(result.DASH_BTC.last_trade), + volume: parseFloat(result.DASH_USD.vol_curr) + }; + callback(null, data); + return; }); }; var fetchFromYobit= function(callback){ + var data = {}; log.debug('Fetching exchange data from ' + AppConfig.exchanges.yobit.name + ' at ' + AppConfig.exchanges.yobit.url); fetchExchangeData(AppConfig.exchanges.yobit.name, AppConfig.exchanges.yobit.url, function(err, result){ if ( err ){ callback(err); - }else{ - var data = { - exchange: AppConfig.exchanges.yobit.name, - url: AppConfig.exchanges.yobit.orgUrl, - price: result.dash_usd.last - }; - data.volume = result.dash_usd.vol*data.price; - callback(null, data); + return; } + if (result === null) { + callback(null, null); + return; + } + data = { + exchange: AppConfig.exchanges.yobit.name, + url: AppConfig.exchanges.yobit.orgUrl, + price: parseFloat(result.dash_usd.last) + }; + data.volume = result.dash_usd.vol*data.price + fetchExchangeData(AppConfig.exchanges.yobit.name, AppConfig.exchanges.yobit.urlBTC, function(err, result){ + if ( err ){ + callback(err); + return; + } + if (result === null) { + callback(null, null); + return; + } + data['price_btc'] = parseFloat(result.dash_btc.last); + fetchExchangeData(AppConfig.exchanges.yobit.name, AppConfig.exchanges.yobit.urlRur, function(err, result){ + if ( err ){ + callback(err); + return; + } + if (result === null) { + callback(null, null); + return; + } + data['price_rur'] = parseFloat(result.dash_rur.last); + callback(null, data); + return; + }); + }); + }); }; var fetchFromCcex= function(callback){ + var data = {}; log.debug('Fetching exchange data from ' + AppConfig.exchanges.ccex.name + ' at ' + AppConfig.exchanges.ccex.url); fetchExchangeData(AppConfig.exchanges.ccex.name, AppConfig.exchanges.ccex.url, function(err, result){ if ( err ){ callback(err); - }else{ - var data = { - exchange: AppConfig.exchanges.ccex.name, - url: AppConfig.exchanges.ccex.orgUrl, - price: result.ticker.lastprice, - }; - callback(null, data); + return; + } + if (result === null) { + callback(null, null); + return; } + data = { + exchange: AppConfig.exchanges.ccex.name, + url: AppConfig.exchanges.ccex.orgUrl, + price: parseFloat(result.ticker.lastprice) + }; + // Fetching BTC price + fetchExchangeData(AppConfig.exchanges.ccex.name, AppConfig.exchanges.ccex.urlBTC, function(err, result){ + if ( err ){ + callback(err); + return; + } + if (result === null) { + callback(null, null); + return; + } + data['price_btc'] = parseFloat(result.ticker.lastprice); + callback(null, data); + return; + }); }); + }; -var fetchFromBithumb= function(callback){ - fetchExchangeData(AppConfig.exchanges.yahoofinance.name, AppConfig.exchanges.yahoofinance.url, function(err, result){ +var fetchFromCexio= function(callback){ + var data = {}; + log.debug('Fetching exchange data from ' + AppConfig.exchanges.cexio.name + ' at ' + AppConfig.exchanges.cexio.url); + fetchExchangeData(AppConfig.exchanges.cexio.name, AppConfig.exchanges.cexio.url, function(err, result){ if ( err ){ callback(err); - }else{ - krwUsd = result.query.results.rate.Rate; - fetchExchangeData(AppConfig.exchanges.bithumb.name, AppConfig.exchanges.bithumb.url, function(err, result){ + return; + } + if (result === null) { + callback(null, null); + return; + } + data = { + exchange: AppConfig.exchanges.cexio.name, + url: AppConfig.exchanges.cexio.orgUrl, + price: parseFloat(result.lprice) + }; + fetchExchangeData(AppConfig.exchanges.cexio.name, AppConfig.exchanges.cexio.urlEur, function(err, result){ + if ( err ){ + callback(err); + return; + } + if (result === null) { + callback(null, null); + return; + } + data['price_eur'] = parseFloat(result.lprice); + fetchExchangeData(AppConfig.exchanges.cexio.name, AppConfig.exchanges.cexio.urlBTC, function(err, result){ if ( err ){ callback(err); - }else{ - var data = { - exchange: AppConfig.exchanges.bithumb.name, - url: AppConfig.exchanges.bithumb.orgUrl, - price: result.data.closing_price*krwUsd, - }; - data.volume = result.data.volume_1day*data.price; - callback(null, data); + return; + } + if (result === null) { + callback(null, null); + return; } + data['price_btc'] = parseFloat(result.lprice); + callback(null, data); + return; }); - } + }); + }); }; -var fetchAll = function(callback){ - var callstack = []; - - Cache.getExchangeData(function(err, data){ +var fetchFromBithumb= function(callback){ + fetchExchangeData(AppConfig.exchanges.CurrencyConverterApi.name, AppConfig.exchanges.CurrencyConverterApi.url, function(err, result){ if ( err ){ callback(err); - }else{ - - if ( data === undefined ){ - - console.log('Latest exchange data not found in cache.'); - - callstack.push(fetchFromCoinCapBtc); - callstack.push(fetchFromWorldCoinIndex); - callstack.push(fetchFromCoinCap); - callstack.push(fetchFromKraken); - callstack.push(fetchFromBittrex); - callstack.push(fetchFromBitfinex); - callstack.push(fetchFromHitbtc); - callstack.push(fetchFromBithumb); - callstack.push(fetchFromLivecoin); - callstack.push(fetchFromExmo); - callstack.push(fetchFromYobit); - callstack.push(fetchFromCcex); - Async.parallel(callstack, function(err, result){ - Cache.storeExchangeData(result); - callback(err,result); - }); - - }else{ - log.debug('Using exchange data found in cache.'); - callback(null,data); + return; + } + if (result === null || result.KRW_USD.val === null) { + callback(null, null); + return; + } + krwUsd = parseFloat(result.KRW_USD.val); + fetchExchangeData(AppConfig.exchanges.bithumb.name, AppConfig.exchanges.bithumb.url, function(err, result){ + if ( err ){ + callback(err); + return; + } + if (result === null) { + callback(null, null); + return; } + if (!result.data){ + callback(createErrorExtension( 'ERROR: unexpected output format', AppConfig.exchanges.bithumb.url, 'undefined'), null); + return; + } + var data = { + exchange: AppConfig.exchanges.bithumb.name, + url: AppConfig.exchanges.bithumb.orgUrl, + price: result.data.closing_price*krwUsd + }; + data.volume = result.data.volume_1day*data.price; + callback(null, data); + return; + }); + }); +}; + +var fetchFromBinance= function(callback){ + var data = {}; + log.debug('Fetching exchange data from ' + AppConfig.exchanges.binance.name + ' at ' + AppConfig.exchanges.binance.url); + fetchExchangeData(AppConfig.exchanges.binance.name, AppConfig.exchanges.binance.url, function(err, result){ + if ( err ){ + callback(err); + return; + } + if (result === null) { + callback(null, null); + return; + } + var dashBtcTicker = result.find(obj => obj.symbol === "DASHBTC"); + if (dashBtcTicker === undefined ) { + callback(createErrorExtension( 'ERROR: unexpected output format', AppConfig.exchanges.binance.url, 'undefined'), null); + return; + } + data = { + exchange: AppConfig.exchanges.binance.name, + url: AppConfig.exchanges.binance.orgUrl, + price_btc: parseFloat(dashBtcTicker.price) + }; + callback(null, data); + return; + }); +}; + +var fetchFromCoinroom = function(callback){ + log.debug('Fetching exchange data from ' + AppConfig.exchanges.coinroom.name + ' at ' + AppConfig.exchanges.coinroom.url); + fetchExchangeData(AppConfig.exchanges.coinroom.name, AppConfig.exchanges.coinroom.url, function(err, result){ + if ( err ){ + callback(err); + return; + } + if (result === null) { + callback(null, null); + return; + } + var data = { + exchange: AppConfig.exchanges.coinroom.name, + url: AppConfig.exchanges.coinroom.orgUrl, + price: parseFloat(result.last) + }; + callback(null, data); + return; + }); +}; + +var fetchFromHuobi = function(callback){ + log.debug('Fetching exchange data from ' + AppConfig.exchanges.huobi.name + ' at ' + AppConfig.exchanges.huobi.url); + fetchExchangeData(AppConfig.exchanges.huobi.name, AppConfig.exchanges.huobi.url, function(err, result){ + if ( err ){ + callback(err); + return; + } + if (result === null) { + callback(null, null); + return; } + var data = { + exchange: AppConfig.exchanges.huobi.name, + url: AppConfig.exchanges.huobi.orgUrl, + price_btc: parseFloat(result.tick.data[0].price) + }; + callback(null, data); + return; + }); +}; +var addUsdPrice = function addUsdPrice(arr, btcPrice){ + updatedResult = arr.filter(function(obj) { + if (!obj){ + return false; + } + if(obj.hasOwnProperty("price_btc") && !obj.hasOwnProperty("price")){ + obj.price = obj["price_btc"]*btcPrice; + } + return obj != undefined; + }); + return updatedResult; +}; + +var fetchAll = function(callback){ + Cache.getExchangeData(function(err, data) { + if (err) { + callback(err); + return; + } + + if (data !== undefined) { + log.debug('Using exchange data found in cache.'); + callback(null, data); + return; + } + + log.debug('Latest exchange data not found in cache.'); + const callstack = { + fetchFromCoinCapBtc, + fetchFromWorldCoinIndex, + fetchFromCoinCap, + fetchFromKraken, + fetchFromBittrex, + fetchFromBitfinex, + fetchFromHitbtc, + fetchFromBithumb, + fetchFromLivecoin, + fetchFromExmo, + fetchFromYobit, + fetchFromPoloniex, + fetchFromCcex, + fetchFromCexio, + fetchFromBinance, + fetchFromCoinroom, + fetchFromHuobi + }; + + Async.parallel(Async.reflectAll(callstack), (err, result)=> { + // preventing unnecessary wrapper with "value" key + let resultArray = Object.values(result).map((obj)=> { + if (obj && obj['value']){ + return obj['value']; + } + return obj; + }); + + const { fetchFromCoinCapBtc: coinCapBtc } = result; + if (coinCapBtc.value && coinCapBtc.value.btcPrice) { + resultArray = addUsdPrice(resultArray, coinCapBtc.value.btcPrice); + } + + Cache.storeExchangeData(resultArray); + callback(null, resultArray); + }); }); - - }; module.exports = { @@ -315,5 +656,8 @@ module.exports = { fetchFromExmo: fetchFromExmo, fetchFromYobit: fetchFromYobit, fetchFromCcex: fetchFromCcex, + fetchFromBinance: fetchFromBinance, + fetchFromCoinroom: fetchFromCoinroom, + fetchFromHuobi: fetchFromHuobi, fetchAll: fetchAll } \ No newline at end of file