WIP -- refactoring

This commit is contained in:
Josh Harvey 2016-04-05 17:41:12 +01:00
parent 8d44c1d383
commit f55e9355ef
3 changed files with 84 additions and 82 deletions

View file

@ -11,18 +11,10 @@ var argv = require('minimist')(process.argv.slice(2))
var tradeInterval = null
var SATOSHI_FACTOR = 1e8
var POLLING_RATE = 60 * 1000 // poll each minute
var REAP_RATE = 2 * 1000
var PENDING_TIMEOUT = 70 * 1000
var BTC_COIN = {
unitCode: 'BTC',
displayCode: 'mBTC',
unitScale: 8,
displayScale: 5
}
if (argv.timeout) PENDING_TIMEOUT = argv.timeout / 1000
// TODO: might have to update this if user is allowed to extend monitoring time
@ -30,10 +22,10 @@ var DEPOSIT_TIMEOUT = 130 * 1000
var db = null
var cryptoCoins = null
var cryptoCodes = null
var tickerPlugins = {}
var traderPlugin = null
var traderPlugins = {}
var walletPlugins = {}
var idVerifierPlugin = null
var infoPlugin = null
@ -46,7 +38,7 @@ var deviceCurrency = 'USD'
var lastBalances = {}
var lastRates = {}
var tradesQueue = []
var tradesQueues = {}
// that's basically a constructor
exports.init = function init (databaseHandle) {
@ -119,9 +111,9 @@ function loadPlugin (name, config) {
return plugin
}
function loadOrConfigPlugin (pluginHandle, pluginType, cryptoCoin, currency,
function loadOrConfigPlugin (pluginHandle, pluginType, cryptoCode, currency,
onChangeCallback) {
var cryptoCode = cryptoCoin ? cryptoCoin.unitCode : 'any'
cryptoCode = cryptoCode || 'BTC'
var currentName = cryptoCode === 'any' || cryptoCode === 'BTC'
? cachedConfig.exchanges.plugins.current[pluginType]
@ -157,19 +149,18 @@ exports.configure = function configure (config) {
cachedConfig = config
deviceCurrency = config.exchanges.settings.currency
cryptoCoins = config.exchanges.settings.coins || [BTC_COIN]
cryptoCodes = config.exchanges.settings.coins || 'BTC'
cryptoCoins.forEach(function (cryptoCoin) {
cryptoCodes.forEach(function (cryptoCode) {
// TICKER [required] configure (or load)
var cryptoCode = cryptoCoin.unitCode
loadOrConfigPlugin(
tickerPlugins[cryptoCode],
'ticker',
cryptoCoin,
cryptoCode,
deviceCurrency, // device currency
function onTickerChange (newTicker) {
tickerPlugins[cryptoCode] = newTicker
pollRate(cryptoCoin)
pollRate(cryptoCode)
}
)
@ -177,28 +168,29 @@ exports.configure = function configure (config) {
loadOrConfigPlugin(
walletPlugins[cryptoCode],
'transfer',
cryptoCoin,
cryptoCode,
null,
function onWalletChange (newWallet) {
walletPlugins[cryptoCode] = newWallet
pollBalance(cryptoCoin)
pollBalance(cryptoCode)
}
)
tradesQueues[cryptoCode] = []
loadOrConfigPlugin(
traderPlugins[cryptoCode],
'trade',
cryptoCode,
null,
function onTraderChange (newTrader) {
traderPlugins[cryptoCode] = newTrader
if (newTrader === null) stopTrader(cryptoCode)
else startTrader(cryptoCode)
}
)
})
// TRADER [optional] configure (or load)
traderPlugin = loadOrConfigPlugin(
traderPlugin,
'trade',
null,
null,
function onTraderChange (newTrader) {
traderPlugin = newTrader
if (newTrader === null) stopTrader()
else startTrader()
}
)
// ID VERIFIER [optional] configure (or load)
idVerifierPlugin = loadOrConfigPlugin(
idVerifierPlugin,
@ -248,14 +240,13 @@ exports.pollQueries = function pollQueries (session, cb) {
})
}
function _sendCoins (toAddress, cryptoAtoms, cryptoCoin, cb) {
var cryptoCode = cryptoCoin.unitCode
function _sendCoins (toAddress, cryptoAtoms, cryptoCode, cb) {
var walletPlugin = walletPlugins[cryptoCode]
var transactionFee = cachedConfig.exchanges.settings.transactionFee
if (cryptoCode === 'BTC') {
walletPlugin.sendBitcoins(toAddress, cryptoAtoms, transactionFee, cb)
} else {
walletPlugin.sendCoins(toAddress, cryptoAtoms, cryptoCoin, transactionFee, cb)
walletPlugin.sendCoins(toAddress, cryptoAtoms, cryptoCode, transactionFee, cb)
}
}
@ -323,10 +314,15 @@ function reapTxs () {
exports.trade = function trade (session, rawTrade, cb) {
// TODO: move this to DB, too
// add bill to trader queue (if trader is enabled)
var cryptoCode = rawTrade.cryptoCode || 'BTC'
var traderPlugin = traderPlugins[cryptoCode]
var tradesQueue = tradesQueues[cryptoCode]
if (traderPlugin) {
tradesQueue.push({
currency: rawTrade.currency,
satoshis: rawTrade.satoshis
cryptoAtoms: rawTrade.cryptoAtoms,
cryptoCode: rawTrade.cryptoCode
})
}
@ -360,9 +356,7 @@ exports.cashOut = function cashOut (session, tx, cb) {
account: 'deposit'
}
var cryptoCoin = tx.coin || BTC_COIN
var cryptoCode = cryptoCoin.unitCode
var cryptoCode = tx.cryptoCode || 'BTC'
var walletPlugin = walletPlugins[cryptoCode]
walletPlugin.newAddress(tmpInfo, function (err, address) {
@ -380,9 +374,8 @@ exports.dispenseAck = function dispenseAck (session, rec) {
db.addDispense(session, rec.tx, rec.cartridges)
}
exports.fiatBalance = function fiatBalance (cryptoCoin) {
var cryptoCode = cryptoCoin.unitCode
var rawRate = exports.getDeviceRate(cryptoCoin).rates.ask
exports.fiatBalance = function fiatBalance (cryptoCode) {
var rawRate = exports.getDeviceRate(cryptoCode).rates.ask
var commission = cachedConfig.exchanges.settings.commission
var lastBalance = lastBalances[cryptoCode]
@ -410,9 +403,9 @@ exports.fiatBalance = function fiatBalance (cryptoCoin) {
exports.startPolling = function startPolling () {
executeTrades()
cryptoCoins.forEach(function (coin) {
setInterval(async.apply(pollBalance, coin), POLLING_RATE)
setInterval(async.apply(pollRate, coin), POLLING_RATE)
cryptoCodes.forEach(function (cryptoCode) {
setInterval(async.apply(pollBalance, cryptoCode), POLLING_RATE)
setInterval(async.apply(pollRate, cryptoCode), POLLING_RATE)
})
setInterval(reapTxs, REAP_RATE)
@ -420,29 +413,30 @@ exports.startPolling = function startPolling () {
startTrader()
}
function startTrader () {
function startTrader (cryptoCode) {
// Always start trading, even if we don't have a trade exchange configured,
// since configuration can always change in `Trader#configure`.
// `Trader#executeTrades` returns early if we don't have a trade exchange
// configured at the moment.
var traderPlugin = traderPlugins[cryptoCode]
if (traderPlugin && !tradeInterval) {
tradeInterval = setInterval(
executeTrades,
function () { executeTrades(cryptoCode) },
cachedConfig.exchanges.settings.tradeInterval
)
}
}
function stopTrader () {
function stopTrader (cryptoCode) {
if (tradeInterval) {
clearInterval(tradeInterval)
tradeInterval = null
tradesQueue = []
tradesQueues[cryptoCode] = []
}
}
function pollBalance (cryptoCoin, cb) {
var cryptoCode = cryptoCoin.unitCode
function pollBalance (cryptoCode, cb) {
logger.debug('[%s] collecting balance', cryptoCode)
var walletPlugin = walletPlugins[cryptoCode]
@ -461,8 +455,7 @@ function pollBalance (cryptoCoin, cb) {
})
}
function pollRate (cryptoCoin, cb) {
var cryptoCode = cryptoCoin.unitCode
function pollRate (cryptoCode, cb) {
logger.debug('[%s] polling for rates (%s)', cryptoCode, tickerPlugin.NAME)
var tickerPlugin = tickerPlugins[cryptoCode]
@ -471,7 +464,7 @@ function pollRate (cryptoCoin, cb) {
var tickerF = cryptoCode === 'BTC'
? async.apply(tickerPlugin.ticker, currencies)
: async.apply(tickerPlugin.ticker, currencies, cryptoCoin)
: async.apply(tickerPlugin.ticker, currencies, cryptoCode)
tickerF(function (err, resRates) {
if (err) {
@ -491,8 +484,7 @@ function pollRate (cryptoCoin, cb) {
* Getters | Helpers
*/
exports.getDeviceRate = function getDeviceRate (cryptoCoin) {
var cryptoCode = cryptoCoin.unitCode
exports.getDeviceRate = function getDeviceRate (cryptoCode) {
if (!lastRates[cryptoCode]) return null
var lastRate = lastRates[cryptoCode]
@ -501,8 +493,7 @@ exports.getDeviceRate = function getDeviceRate (cryptoCoin) {
return lastRate[deviceCurrency]
}
exports.getBalance = function getBalance (cryptoCoin) {
var cryptoCode = cryptoCoin.unitCode
exports.getBalance = function getBalance (cryptoCode) {
var lastBalance = lastBalances[cryptoCode]
if (!lastBalance) return null
@ -513,44 +504,50 @@ exports.getBalance = function getBalance (cryptoCoin) {
* Trader functions
*/
function purchase (trade, cb) {
var cryptoCode = trade.cryptoCode
var traderPlugin = traderPlugins[cryptoCode]
traderPlugin.purchase(trade.satoshis, null, function (err) {
if (err) return cb(err)
pollBalance('BTC')
pollBalance(cryptoCode)
if (typeof cb === 'function') cb()
})
}
function consolidateTrades () {
function consolidateTrades (cryptoCode) {
// NOTE: value in satoshis stays the same no matter the currency
var cryptoAtoms = tradesQueues[cryptoCode].reduce(function (prev, current) {
return current.cryptoAtoms.plus(prev)
}, new BigNumber(0))
var consolidatedTrade = {
currency: deviceCurrency,
satoshis: tradesQueue.reduce(function (prev, current) {
return prev + current.satoshis
}, 0)
cryptoAtoms: cryptoAtoms,
cryptoCode: cryptoCode
}
tradesQueue = []
tradesQueues[cryptoCode] = []
logger.debug('consolidated: ', JSON.stringify(consolidatedTrade))
return consolidatedTrade
}
function executeTrades () {
function executeTrades (cryptoCode) {
var traderPlugin = traderPlugins[cryptoCode]
if (!traderPlugin) return
logger.debug('checking for trades')
var trade = consolidateTrades()
var trade = consolidateTrades(cryptoCode)
if (trade.satoshis === 0) {
if (trade.cryptoAtoms.eq(0)) {
logger.debug('rejecting 0 trade')
return
}
logger.debug('making a trade: %d', trade.satoshis / SATOSHI_FACTOR)
logger.debug('making a trade: %d', trade.cryptoAtoms.toString())
purchase(trade, function (err) {
if (err) {
tradesQueue.push(trade)
tradesQueues[cryptoCode].push(trade)
if (err.name !== 'orderTooSmall') logger.error(err)
}
})
@ -567,6 +564,6 @@ exports.verifyTx = function verifyTx (data, cb) {
idVerifierPlugin.verifyTransaction(data, cb)
}
exports.getCryptoCoins = function getCryptoCoins () {
return cryptoCoins
exports.getcryptoCodes = function getcryptoCodes () {
return cryptoCodes
}