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 ccxt = require('./plugins/exchange/ccxt')
const mockExchange = require('./plugins/exchange/mock-exchange')
function lookupExchange (settings, cryptoCode) {
const exchange = configManager.getWalletSettings(cryptoCode, settings.config).exchange
@ -20,12 +21,22 @@ function fetchExchange (settings, cryptoCode) {
function buy (settings, cryptoAtoms, fiatCode, 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) {
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) {

View file

@ -1,28 +1,32 @@
const _ = require('lodash/fp')
const CRYPTO = {
bitstamp: ['BTC', 'ETH', 'LTC', 'BCH'],
itbit: ['BTC', 'ETH', 'LTC', 'BCH'],
kraken: ['BTC', 'ETH', 'LTC', 'DASH', 'ZEC', 'BCH'],
coinbase: ['BTC', 'ETH', 'LTC', 'BCH', 'ZEC', 'DASH']
const kraken = require('../exchange/kraken')
const bitstamp = require('../exchange/bitstamp')
const itbit = require('../exchange/itbit')
const bitpay = require('../ticker/bitpay')
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 = {
bitstamp: ['USD', 'EUR'],
itbit: ['USD'],
kraken: ['USD', 'EUR']
}
function verifyCurrencies (exchangeName, fiatCode, cryptoCode) {
if (!_.includes(cryptoCode, CRYPTO[exchangeName])) {
function buildMarket (fiatCode, cryptoCode, serviceName) {
if (!_.includes(cryptoCode, ALL[serviceName].CRYPTO)) {
throw new Error('Unsupported crypto: ' + cryptoCode)
}
if (exchangeName !== 'coinbase') {
if (!_.includes(fiatCode, FIAT[exchangeName])) {
const fiatSupported = ALL[serviceName].FIAT
if (fiatSupported !== 'ALL_CURRENCIES' && !_.includes(fiatCode, fiatSupported)) {
throw new Error('Unsupported fiat: ' + 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 consts = require('./consts')
const ORDER_TYPE = consts.ORDER_TYPES.MARKET
const FIAT = common.FIAT['kraken']
const CRYPTO = common.CRYPTO['kraken']
const { ORDER_TYPES } = require('./consts')
const { COINS } = require('../../new-admin/config/coins')
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 mapper = {
@ -16,6 +20,4 @@ const loadConfig = (account) => {
const isConfigValid = ({ key, clientId, secret }) => key && secret && clientId
const amountPrecision = () => 8
module.exports = { loadConfig, isConfigValid, amountPrecision , CRYPTO, FIAT, ORDER_TYPE }
module.exports = { loadConfig, isConfigValid, CRYPTO, FIAT, ORDER_TYPE, AMOUNT_PRECISION }

View file

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

View file

@ -3,9 +3,5 @@ const ORDER_TYPES = {
MARKET: 'market',
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 consts = require('./consts')
const ORDER_TYPE = consts.ORDER_TYPES.LIMIT
const FIAT = common.FIAT['kraken']
const CRYPTO = common.CRYPTO['kraken']
const { ORDER_TYPES } = require('./consts')
const { COINS } = require('../../new-admin/config/coins') // para cada exchange
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 mapper = {
@ -17,6 +21,4 @@ const loadConfig = (account) => {
const loadOptions = ({ walletId }) => ({ walletId })
const isConfigValid = ({ clientKey, clientSecret, userId, walletId }) => clientKey && clientSecret && userId && walletId
const amountPrecision = () => 4
module.exports = { amountPrecision, loadOptions, loadConfig, isConfigValid, CRYPTO, FIAT, ORDER_TYPE }
module.exports = { loadOptions, loadConfig, isConfigValid, CRYPTO, FIAT, ORDER_TYPE, AMOUNT_PRECISION }

View file

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

View file

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

View file

@ -1,7 +1,12 @@
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)
.then(r => {
const data = r.data.data
@ -17,5 +22,7 @@ function ticker (account, fiatCode, cryptoCode) {
module.exports = {
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 common = require('../common/ccxt')
const axios = require('axios')
const ccxt = require('ccxt')
function ticker (exchangeName, fiatCode, cryptoCode) {
const exchange = new ccxt[exchangeName]()
const BN = require('../../bn')
const { buildMarket } = require('../common/ccxt')
if (fiatCode === 'EUR' || fiatCode === 'USD' || exchange.id === 'coinbase') {
return getCurrencyRates(exchange, fiatCode, cryptoCode)
function ticker (fiatCode, cryptoCode, tickerName) {
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')
@ -18,7 +18,7 @@ function ticker (exchangeName, fiatCode, cryptoCode) {
const usdRate = findCurrencyRates(fxRates, 'USD')
const fxRate = findCurrencyRates(fxRates, fiatCode).div(usdRate)
return getCurrencyRates(exchange, 'USD', cryptoCode)
return getCurrencyRates(ticker, 'USD', cryptoCode)
.then(res => ({
rates: {
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 {
if (exchange.has['fetchTicker']) {
const symbol = common.verifyCurrencies(exchange.id, fiatCode, cryptoCode)
return exchange.fetchTicker(symbol)
if (ticker.has['fetchTicker']) {
const symbol = buildMarket(fiatCode, cryptoCode, ticker.id)
return ticker.fetchTicker(symbol)
.then(res => ({
rates: {
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({
rates: {
ask: BN(105),

View file

@ -1,19 +1,22 @@
const mem = require('mem')
const configManager = require('./new-config-manager')
const logger = require('./logger')
const ccxt = require('./plugins/ticker/ccxt')
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
function _getRates (settings, fiatCode, cryptoCode) {
return Promise.resolve()
.then(() => {
const config = settings.config
const exchangeName = configManager.getWalletSettings(cryptoCode, config).ticker
const tickerName = configManager.getWalletSettings(cryptoCode, config).ticker
const market = [cryptoCode, fiatCode].join('-')
return ccxt.ticker(exchangeName, fiatCode, cryptoCode)
return buildTicker(fiatCode, cryptoCode, tickerName)
.then(r => ({
rates: r.rates,
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, {
maxAge: FETCH_INTERVAL,
cacheKey: (settings, fiatCode, cryptoCode) => JSON.stringify([fiatCode, cryptoCode])