UNPKG

bitcore-wallet-service

Version:
307 lines 12.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FiatRateService = void 0; const async = __importStar(require("async")); const request = __importStar(require("request")); const common_1 = require("./common"); const fiatrateproviders_1 = require("./fiatrateproviders"); const logger_1 = __importDefault(require("./logger")); const storage_1 = require("./storage"); const $ = require('preconditions').singleton(); const Defaults = common_1.Common.Defaults; const Constants = common_1.Common.Constants; class FiatRateService { init(opts, cb) { opts = opts || {}; this.request = opts.request || request; this.defaultProvider = opts.defaultProvider || Defaults.FIAT_RATE_PROVIDER; async.parallel([ done => { if (opts.storage) { this.storage = opts.storage; done(); } else { this.storage = new storage_1.Storage(); this.storage.connect(opts.storageOpts, done); } } ], err => { if (err) { logger_1.default.error('%o', err); } return cb(err); }); } startCron(opts, cb) { opts = opts || {}; this.providers = fiatrateproviders_1.providers; const interval = opts.fetchInterval || Defaults.FIAT_RATE_FETCH_INTERVAL; if (interval) { this._fetch(); setInterval(() => { this._fetch(); }, interval * 60 * 1000); } return cb(); } _fetch(cb) { cb = cb || function () { }; const coins = Object.values(Constants.BITPAY_SUPPORTED_COINS); const provider = this.providers[0]; async.each(coins, (coin, next2) => { this._retrieve(provider, coin, (err, res) => { if (err) { logger_1.default.warn('Error retrieving data for %o->%o: %o', provider.name, coin, err); return next2(); } this.storage.storeFiatRate(coin, res, err => { if (err) { logger_1.default.warn('Error storing data for %o: %o', provider.name, err); } return next2(); }); }); }, cb); } _retrieve(provider, coin, cb) { logger_1.default.debug(`Fetching data for ${provider.name} / ${coin}`); const coinUC = coin.toUpperCase(); const handleCoinsRates = (err, res) => { if (err || !res || res.error) { return cb(err || new Error('Unable to fetch rates data for ' + provider.name + ' / ' + coin + ': ' + res?.error)); } logger_1.default.debug(`Data for ${provider.name} / ${coin} fetched successfully`); if (!provider.parseFn) { return cb(new Error('No parse function for provider ' + provider.name)); } try { const rates = provider.parseFn(res)?.filter(x => Defaults.FIAT_CURRENCIES.some(c => c.code == x.code)) || []; return cb(null, rates); } catch (e) { return cb(e); } }; const ts = Date.now(); if (Constants.BITPAY_USD_STABLECOINS[coinUC]) { return this.getRatesForStablecoin({ code: 'USD', ts }, handleCoinsRates); } if (Constants.BITPAY_EUR_STABLECOINS[coinUC]) { return this.getRatesForStablecoin({ code: 'EUR', ts }, handleCoinsRates); } this.request.get({ url: provider.getUrl(coinUC), json: true }, (err, res, body) => handleCoinsRates(err, body)); } getRate(opts, cb) { $.shouldBeFunction(cb, 'Failed state: type error (cb not a function) at <getRate()>'); opts = opts || {}; const now = Date.now(); let coin = opts.coin || 'btc'; const ts = !isNaN(opts.ts) || Array.isArray(opts.ts) ? opts.ts : now; async.map([].concat(ts), (ts, cb) => { if (coin === 'wbtc') { logger_1.default.info('Using btc for wbtc rate.'); coin = 'btc'; } if (coin === 'weth') { logger_1.default.info('Using eth for weth rate.'); coin = 'eth'; } this.storage.fetchFiatRate(coin, opts.code, ts, (err, rate) => { if (err) return cb(err); if (rate && ts - rate.ts > Defaults.FIAT_RATE_MAX_LOOK_BACK_TIME * 60 * 1000) rate = null; return cb(null, { ts: +ts, rate: rate?.value, fetchedOn: rate?.ts }); }); }, (err, res) => { if (err) return cb(err); if (!Array.isArray(ts)) res = res[0]; return cb(null, res); }); } getRates(opts, cb) { $.shouldBeFunction(cb, 'Failed state: type error (cb not a function) at <getRates()>'); opts = opts || {}; const now = Date.now(); const ts = opts.ts ? opts.ts : now; let fiatFiltered = []; let rates = []; if (opts.code) { fiatFiltered = Defaults.FIAT_CURRENCIES.filter(c => c.code === opts.code); if (!fiatFiltered.length) return cb(opts.code + ' is not supported'); } const currencies = fiatFiltered.length ? fiatFiltered : Defaults.FIAT_CURRENCIES; async.map(Object.values(Constants.BITPAY_SUPPORTED_COINS), (coin, cb) => { rates[coin] = []; async.map(currencies, (currency, cb) => { let c = coin.split('_')[0]; if (c === 'wbtc') { logger_1.default.info('Using btc for wbtc rate.'); c = 'btc'; } if (c === 'weth') { logger_1.default.info('Using eth for weth rate.'); c = 'eth'; } this.storage.fetchFiatRate(c, currency.code, ts, (err, rate) => { if (err) return cb(err); if (rate && ts - rate.ts > Defaults.FIAT_RATE_MAX_LOOK_BACK_TIME * 60 * 1000) rate = null; return cb(null, { ts: +ts, rate: rate?.value, fetchedOn: rate?.ts, code: currency.code, name: currency.name }); }); }, (err, res) => { if (err) return cb(err); var obj = {}; obj[coin] = res; return cb(null, obj); }); }, (err, res) => { if (err) return cb(err); return cb(null, Object.assign({}, ...res)); }); } getRatesByCoin(opts, cb) { $.shouldBeFunction(cb, 'Failed state: type error (cb not a function) at <getRatesByCoin()>'); let { coin, code } = opts; const ts = opts.ts || Date.now(); if (Constants.BITPAY_USD_STABLECOINS[coin.toUpperCase()]) { return this.getRatesForStablecoin({ code: 'USD', ts }, cb); } if (Constants.BITPAY_EUR_STABLECOINS[coin.toUpperCase()]) { return this.getRatesForStablecoin({ code: 'EUR', ts }, cb); } let fiatFiltered = []; if (code) { fiatFiltered = Defaults.FIAT_CURRENCIES.filter(c => c.code === opts.code); if (!fiatFiltered.length) return cb(opts.code + ' is not supported'); } const currencies = fiatFiltered.length ? fiatFiltered : Defaults.FIAT_CURRENCIES; async.map(currencies, (currency, cb) => { if (coin === 'wbtc') { logger_1.default.info('Using btc for wbtc rate.'); coin = 'btc'; } if (coin === 'weth') { logger_1.default.info('Using eth for weth rate.'); coin = 'eth'; } this.storage.fetchFiatRate(coin, currency.code, ts, (err, rate) => { if (err) return cb(err); if (rate && ts - rate.ts > Defaults.FIAT_RATE_MAX_LOOK_BACK_TIME * 60 * 1000) rate = null; return cb(null, { ts: +ts, rate: rate?.value, fetchedOn: rate?.ts, code: currency.code, name: currency.name }); }); }, cb); } getHistoricalRates(opts, cb) { $.shouldBeFunction(cb); opts = opts || {}; const historicalRates = {}; const now = Date.now() - Defaults.FIAT_RATE_FETCH_INTERVAL * 60 * 1000; const ts = !isNaN(opts.ts) ? opts.ts : now; const coins = ['btc', 'bch', 'eth', 'matic', 'xrp', 'doge', 'ltc', 'shib', 'ape', 'sol']; async.map(coins, (coin, cb) => { this.storage.fetchHistoricalRates(coin, opts.code, ts, (err, rates) => { if (err) return cb(err); if (!rates) return cb(); for (const rate of rates) { rate.rate = rate.value; delete rate['_id']; delete rate['code']; delete rate['value']; delete rate['coin']; } historicalRates[coin] = rates; return cb(null, historicalRates); }); }, (err, res) => { if (err) return cb(err); return cb(null, res[0]); }); } getRatesForStablecoin(opts, cb) { $.shouldBeFunction(cb, 'Failed state: type error (cb not a function) at <getRatesForStablecoin()>'); const { coin = 'btc', code } = opts; const ts = opts.ts || Date.now(); this.getRatesByCoin({ coin, ts }, (err, rates) => { if (err) return cb(err); const fiatRate = rates.find(rate => rate.code === code); if (!fiatRate || !fiatRate.rate) return cb(null, []); return cb(null, rates.map(({ rate, ...obj }) => ({ ...obj, rate: parseFloat((rate / fiatRate.rate).toFixed(2)) }))); }); } } exports.FiatRateService = FiatRateService; //# sourceMappingURL=fiatrateservice.js.map