Code readability and added the forgotten mocks

This commit is contained in:
José Oliveira 2021-01-25 23:51:39 +00:00 committed by Josh Harvey
parent 134eaaa518
commit 7accdaa84f
12 changed files with 126 additions and 96 deletions

View file

@ -1,5 +1,6 @@
const configManager = require('./new-config-manager') const configManager = require('./new-config-manager')
const ccxt = require('./plugins/exchange/ccxt') const ccxt = require('./plugins/exchange/ccxt')
const mockExchange = require('./plugins/exchange/mock-exchange')
function lookupExchange (settings, cryptoCode) { function lookupExchange (settings, cryptoCode) {
const exchange = configManager.getWalletSettings(cryptoCode, settings.config).exchange const exchange = configManager.getWalletSettings(cryptoCode, settings.config).exchange
@ -20,12 +21,22 @@ function fetchExchange (settings, cryptoCode) {
function buy (settings, cryptoAtoms, fiatCode, cryptoCode) { function buy (settings, cryptoAtoms, fiatCode, cryptoCode) {
return fetchExchange(settings, cryptoCode) return fetchExchange(settings, cryptoCode)
.then(r => ccxt.trade('buy', r.account, cryptoAtoms, fiatCode, cryptoCode, r.exchangeName)) .then(r => {
if (r.exchangeName === 'mock-exchange') {
return mockExchange.buy(cryptoAtoms, fiatCode, cryptoCode)
}
return ccxt.trade('buy', r.account, cryptoAtoms, fiatCode, cryptoCode, r.exchangeName)
})
} }
function sell (settings, cryptoAtoms, fiatCode, cryptoCode) { function sell (settings, cryptoAtoms, fiatCode, cryptoCode) {
return fetchExchange(settings, cryptoCode) return fetchExchange(settings, cryptoCode)
.then(r => ccxt.trade('sell', r.account, cryptoAtoms, fiatCode, cryptoCode, r.exchangeName)) .then(r => {
if (r.exchangeName === 'mock-exchange') {
return mockExchange.sell(cryptoAtoms, fiatCode, cryptoCode)
}
return ccxt.trade('sell', r.account, cryptoAtoms, fiatCode, cryptoCode, r.exchangeName)
})
} }
function active (settings, cryptoCode) { function active (settings, cryptoCode) {

View file

@ -1,28 +1,32 @@
const _ = require('lodash/fp') const _ = require('lodash/fp')
const CRYPTO = { const kraken = require('../exchange/kraken')
bitstamp: ['BTC', 'ETH', 'LTC', 'BCH'], const bitstamp = require('../exchange/bitstamp')
itbit: ['BTC', 'ETH', 'LTC', 'BCH'], const itbit = require('../exchange/itbit')
kraken: ['BTC', 'ETH', 'LTC', 'DASH', 'ZEC', 'BCH'], const bitpay = require('../ticker/bitpay')
coinbase: ['BTC', 'ETH', 'LTC', 'BCH', 'ZEC', 'DASH'] const { COINS } = require('../../new-admin/config/coins')
const { BTC, BCH, DASH, ETH, LTC, ZEC } = COINS
const ALL = {
kraken: kraken,
bitstamp: bitstamp,
itbit: itbit,
bitpay: bitpay,
coinbase: {
CRYPTO: [BTC, ETH, LTC, DASH, ZEC, BCH],
FIAT: 'ALL_CURRENCIES'
}
} }
const FIAT = { function buildMarket (fiatCode, cryptoCode, serviceName) {
bitstamp: ['USD', 'EUR'], if (!_.includes(cryptoCode, ALL[serviceName].CRYPTO)) {
itbit: ['USD'],
kraken: ['USD', 'EUR']
}
function verifyCurrencies (exchangeName, fiatCode, cryptoCode) {
if (!_.includes(cryptoCode, CRYPTO[exchangeName])) {
throw new Error('Unsupported crypto: ' + cryptoCode) throw new Error('Unsupported crypto: ' + cryptoCode)
} }
if (exchangeName !== 'coinbase') { const fiatSupported = ALL[serviceName].FIAT
if (!_.includes(fiatCode, FIAT[exchangeName])) { if (fiatSupported !== 'ALL_CURRENCIES' && !_.includes(fiatCode, fiatSupported)) {
throw new Error('Unsupported fiat: ' + fiatCode) throw new Error('Unsupported fiat: ' + fiatCode)
}
} }
return cryptoCode + '/' + fiatCode return cryptoCode + '/' + fiatCode
} }
module.exports = { verifyCurrencies, CRYPTO, FIAT } module.exports = { buildMarket, ALL }

View file

@ -1,9 +1,13 @@
const common = require('../common/ccxt')
const _ = require('lodash/fp') const _ = require('lodash/fp')
const consts = require('./consts')
const ORDER_TYPE = consts.ORDER_TYPES.MARKET const { ORDER_TYPES } = require('./consts')
const FIAT = common.FIAT['kraken'] const { COINS } = require('../../new-admin/config/coins')
const CRYPTO = common.CRYPTO['kraken']
const ORDER_TYPE = ORDER_TYPES.MARKET
const { BTC, ETH, LTC, BCH } = COINS
const CRYPTO = [BTC, ETH, LTC, BCH]
const FIAT = ['USD', 'EUR']
const AMOUNT_PRECISION = 8
const loadConfig = (account) => { const loadConfig = (account) => {
const mapper = { const mapper = {
@ -16,6 +20,4 @@ const loadConfig = (account) => {
const isConfigValid = ({ key, clientId, secret }) => key && secret && clientId const isConfigValid = ({ key, clientId, secret }) => key && secret && clientId
const amountPrecision = () => 8 module.exports = { loadConfig, isConfigValid, CRYPTO, FIAT, ORDER_TYPE, AMOUNT_PRECISION }
module.exports = { loadConfig, isConfigValid, amountPrecision , CRYPTO, FIAT, ORDER_TYPE }

View file

@ -1,37 +1,34 @@
var ccxt = require('ccxt') const _ = require('lodash/fp')
const coinUtils = require('../../coin-utils') const ccxt = require('ccxt')
const common = require('../common/ccxt')
const kraken = require('./kraken')
const bitstamp = require('./bitstamp')
const itbit = require('./itbit')
const consts = require('./consts')
const ALL_EXCHANGES = { const { toUnit } = require('../../coin-utils')
kraken, const { buildMarket, ALL } = require('../common/ccxt')
bitstamp, const { ORDER_TYPES } = require('./consts')
itbit
} const DEFAULT_PRICE_PRECISION = 2
const DEFAULT_AMOUNT_PRECISION = 8
function trade (side, account, cryptoAtoms, fiatCode, cryptoCode, exchangeName) { function trade (side, account, cryptoAtoms, fiatCode, cryptoCode, exchangeName) {
try { try {
const exchangeConfig = ALL_EXCHANGES[exchangeName] const exchangeConfig = ALL[exchangeName]
if (!exchangeConfig) throw Error('Exchange configuration not found')
if (!exchangeConfig) throw Error('no exchange') const { loadOptions, loadConfig = _.noop, isConfigValid, ORDER_TYPE, AMOUNT_PRECISION } = exchangeConfig
if (exchangeConfig.isConfigValid && !exchangeConfig.isConfigValid(account)) throw Error('Invalid config') if (_.isFunction(isConfigValid) && !isConfigValid(account)) throw Error('Invalid config')
const exchange = new ccxt[exchangeName](exchangeConfig.loadConfig(account)) const symbol = buildMarket(fiatCode, cryptoCode, exchangeName)
const precision = _.defaultTo(DEFAULT_AMOUNT_PRECISION, AMOUNT_PRECISION)
const amount = toUnit(cryptoAtoms, cryptoCode).toFixed(precision)
const options = _.isFunction(loadOptions) ? loadOptions(account) : {}
const exchange = new ccxt[exchangeName](loadConfig(account))
const symbol = common.verifyCurrencies(exchangeName, fiatCode, cryptoCode) if (ORDER_TYPE === ORDER_TYPES.MARKET) {
const precision = exchangeConfig.amountPrecision ? exchangeConfig.amountPrecision() : consts.DECIMAL_PRECISION.DEFAULT_AMOUNT return exchange.createOrder(symbol, ORDER_TYPES.MARKET, side, amount, null, options)
const amount = coinUtils.toUnit(cryptoAtoms, cryptoCode).toFixed(precision)
const options = exchangeConfig.loadOptions ? exchangeConfig.loadOptions(account) : {}
if (exchangeConfig.ORDER_TYPE === consts.ORDER_TYPES.MARKET) {
return exchange.createOrder(symbol, consts.ORDER_TYPES.MARKET, side, amount, null, options)
} }
return exchange.fetchOrderBook(symbol) return exchange.fetchOrderBook(symbol)
.then(orderBook => { .then(orderBook => {
const price = calculatePrice(side, amount, orderBook).toFixed(consts.DECIMAL_PRECISION.PRICE) const price = calculatePrice(side, amount, orderBook).toFixed(DEFAULT_PRICE_PRECISION)
return exchange.createOrder(symbol, consts.ORDER_TYPES.LIMIT, side, amount, price, options) return exchange.createOrder(symbol, ORDER_TYPES.LIMIT, side, amount, price, options)
}) })
} catch (e) { } catch (e) {
return Promise.reject(e) return Promise.reject(e)

View file

@ -3,9 +3,5 @@ const ORDER_TYPES = {
MARKET: 'market', MARKET: 'market',
LIMIT: 'limit' LIMIT: 'limit'
} }
const DECIMAL_PRECISION = {
PRICE: 2,
DEFAULT_AMOUNT: 8
}
module.exports = { ORDER_TYPES, DECIMAL_PRECISION } module.exports = { ORDER_TYPES }

View file

@ -1,9 +1,13 @@
const common = require('../common/ccxt')
const _ = require('lodash/fp') const _ = require('lodash/fp')
const consts = require('./consts')
const ORDER_TYPE = consts.ORDER_TYPES.LIMIT const { ORDER_TYPES } = require('./consts')
const FIAT = common.FIAT['kraken'] const { COINS } = require('../../new-admin/config/coins') // para cada exchange
const CRYPTO = common.CRYPTO['kraken']
const ORDER_TYPE = ORDER_TYPES.LIMIT
const { BTC, ETH, LTC, BCH } = COINS
const CRYPTO = [BTC, ETH, LTC, BCH]
const FIAT = ['USD']
const AMOUNT_PRECISION = 4
const loadConfig = (account) => { const loadConfig = (account) => {
const mapper = { const mapper = {
@ -17,6 +21,4 @@ const loadConfig = (account) => {
const loadOptions = ({ walletId }) => ({ walletId }) const loadOptions = ({ walletId }) => ({ walletId })
const isConfigValid = ({ clientKey, clientSecret, userId, walletId }) => clientKey && clientSecret && userId && walletId const isConfigValid = ({ clientKey, clientSecret, userId, walletId }) => clientKey && clientSecret && userId && walletId
const amountPrecision = () => 4 module.exports = { loadOptions, loadConfig, isConfigValid, CRYPTO, FIAT, ORDER_TYPE, AMOUNT_PRECISION }
module.exports = { amountPrecision, loadOptions, loadConfig, isConfigValid, CRYPTO, FIAT, ORDER_TYPE }

View file

@ -1,9 +1,13 @@
const common = require('../common/ccxt')
const _ = require('lodash/fp') const _ = require('lodash/fp')
const consts = require('./consts')
const ORDER_TYPE = consts.ORDER_TYPES.MARKET const { ORDER_TYPES } = require('./consts')
const FIAT = common.FIAT['kraken'] const { COINS } = require('../../new-admin/config/coins')
const CRYPTO = common.CRYPTO['kraken']
const ORDER_TYPE = ORDER_TYPES.MARKET
const { BTC, BCH, DASH, ETH, LTC, ZEC } = COINS
const CRYPTO = [BTC, ETH, LTC, DASH, ZEC, BCH]
const FIAT = ['USD', 'EUR']
const AMOUNT_PRECISION = 6
const loadConfig = (account) => { const loadConfig = (account) => {
const mapper = { const mapper = {
@ -16,6 +20,4 @@ const loadConfig = (account) => {
const loadOptions = () => ({ expiretm: '+60' }) const loadOptions = () => ({ expiretm: '+60' })
const isConfigValid = ({ apiKey, privateKey }) => apiKey && privateKey const isConfigValid = ({ apiKey, privateKey }) => apiKey && privateKey
const amountPrecision = () => 6 module.exports = { loadOptions, loadConfig, isConfigValid, CRYPTO, FIAT, ORDER_TYPE, AMOUNT_PRECISION }
module.exports = { amountPrecision, loadOptions, loadConfig, isConfigValid, CRYPTO, FIAT, ORDER_TYPE }

View file

@ -3,12 +3,12 @@ module.exports = {
sell sell
} }
function buy (account, cryptoAtoms, fiatCode, cryptoCode) { function buy (cryptoAtoms, fiatCode, cryptoCode) {
console.log('[mock] buying %s %s for %s', cryptoAtoms.toString(), cryptoCode, fiatCode) console.log('[mock] buying %s %s for %s', cryptoAtoms.toString(), cryptoCode, fiatCode)
return Promise.resolve() return Promise.resolve()
} }
function sell (account, cryptoAtoms, fiatCode, cryptoCode) { function sell (cryptoAtoms, fiatCode, cryptoCode) {
console.log('[mock] selling %s %s for %s', cryptoAtoms.toString(), cryptoCode, fiatCode) console.log('[mock] selling %s %s for %s', cryptoAtoms.toString(), cryptoCode, fiatCode)
return Promise.resolve() return Promise.resolve()
} }

View file

@ -1,7 +1,12 @@
const axios = require('axios') const axios = require('axios')
const BN = require('../../../bn')
function ticker (account, fiatCode, cryptoCode) { const BN = require('../../bn')
const { BTC, BCH } = require('../../new-admin/config/coins')
const CRYPTO = [BTC, BCH]
const FIAT = 'ALL_CURRENCIES'
function ticker (fiatCode, cryptoCode) {
return axios.get('https://bitpay.com/rates/' + cryptoCode + '/' + fiatCode) return axios.get('https://bitpay.com/rates/' + cryptoCode + '/' + fiatCode)
.then(r => { .then(r => {
const data = r.data.data const data = r.data.data
@ -17,5 +22,7 @@ function ticker (account, fiatCode, cryptoCode) {
module.exports = { module.exports = {
ticker, ticker,
name: 'BitPay' name: 'BitPay',
CRYPTO,
FIAT
} }

View file

@ -1,14 +1,14 @@
const ccxt = require('ccxt')
const BN = require('../../bn')
const axios = require('axios')
const _ = require('lodash/fp') const _ = require('lodash/fp')
const common = require('../common/ccxt') const axios = require('axios')
const ccxt = require('ccxt')
function ticker (exchangeName, fiatCode, cryptoCode) { const BN = require('../../bn')
const exchange = new ccxt[exchangeName]() const { buildMarket } = require('../common/ccxt')
if (fiatCode === 'EUR' || fiatCode === 'USD' || exchange.id === 'coinbase') { function ticker (fiatCode, cryptoCode, tickerName) {
return getCurrencyRates(exchange, fiatCode, cryptoCode) const ticker = new ccxt[tickerName]({ timeout: 3000 })
if (fiatCode === 'EUR' || fiatCode === 'USD' || ticker.id === 'coinbase') {
return getCurrencyRates(ticker, fiatCode, cryptoCode)
} }
return axios.get('https://bitpay.com/rates') return axios.get('https://bitpay.com/rates')
@ -18,7 +18,7 @@ function ticker (exchangeName, fiatCode, cryptoCode) {
const usdRate = findCurrencyRates(fxRates, 'USD') const usdRate = findCurrencyRates(fxRates, 'USD')
const fxRate = findCurrencyRates(fxRates, fiatCode).div(usdRate) const fxRate = findCurrencyRates(fxRates, fiatCode).div(usdRate)
return getCurrencyRates(exchange, 'USD', cryptoCode) return getCurrencyRates(ticker, 'USD', cryptoCode)
.then(res => ({ .then(res => ({
rates: { rates: {
ask: res.rates.ask.times(fxRate), ask: res.rates.ask.times(fxRate),
@ -31,11 +31,11 @@ function ticker (exchangeName, fiatCode, cryptoCode) {
}) })
} }
function getCurrencyRates (exchange, fiatCode, cryptoCode) { function getCurrencyRates (ticker, fiatCode, cryptoCode) {
try { try {
if (exchange.has['fetchTicker']) { if (ticker.has['fetchTicker']) {
const symbol = common.verifyCurrencies(exchange.id, fiatCode, cryptoCode) const symbol = buildMarket(fiatCode, cryptoCode, ticker.id)
return exchange.fetchTicker(symbol) return ticker.fetchTicker(symbol)
.then(res => ({ .then(res => ({
rates: { rates: {
ask: BN(res.ask), ask: BN(res.ask),

View file

@ -1,6 +1,6 @@
const BN = require('../../../bn') const BN = require('../../bn')
function ticker (account, fiatCode, cryptoCode) { function ticker (fiatCode, cryptoCode) {
return Promise.resolve({ return Promise.resolve({
rates: { rates: {
ask: BN(105), ask: BN(105),

View file

@ -1,19 +1,22 @@
const mem = require('mem') const mem = require('mem')
const configManager = require('./new-config-manager') const configManager = require('./new-config-manager')
const logger = require('./logger') const logger = require('./logger')
const ccxt = require('./plugins/ticker/ccxt')
const lastRate = {} const lastRate = {}
const ccxt = require('./plugins/ticker/ccxt')
const mockTicker = require('./plugins/ticker/mock-ticker')
const bitpay = require('./plugins/ticker/bitpay')
const FETCH_INTERVAL = 60000 const FETCH_INTERVAL = 60000
function _getRates (settings, fiatCode, cryptoCode) { function _getRates (settings, fiatCode, cryptoCode) {
return Promise.resolve() return Promise.resolve()
.then(() => { .then(() => {
const config = settings.config const config = settings.config
const exchangeName = configManager.getWalletSettings(cryptoCode, config).ticker const tickerName = configManager.getWalletSettings(cryptoCode, config).ticker
const market = [cryptoCode, fiatCode].join('-') const market = [cryptoCode, fiatCode].join('-')
return ccxt.ticker(exchangeName, fiatCode, cryptoCode) return buildTicker(fiatCode, cryptoCode, tickerName)
.then(r => ({ .then(r => ({
rates: r.rates, rates: r.rates,
timestamp: Date.now() timestamp: Date.now()
@ -29,6 +32,12 @@ function _getRates (settings, fiatCode, cryptoCode) {
}) })
} }
function buildTicker (fiatCode, cryptoCode, tickerName) {
if (tickerName === 'bitpay') return bitpay.ticker(fiatCode, cryptoCode)
if (tickerName === 'mock-ticker') return mockTicker.ticker(fiatCode, cryptoCode)
return ccxt.ticker(fiatCode, cryptoCode, tickerName)
}
const getRates = mem(_getRates, { const getRates = mem(_getRates, {
maxAge: FETCH_INTERVAL, maxAge: FETCH_INTERVAL,
cacheKey: (settings, fiatCode, cryptoCode) => JSON.stringify([fiatCode, cryptoCode]) cacheKey: (settings, fiatCode, cryptoCode) => JSON.stringify([fiatCode, cryptoCode])