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

View file

@ -23,7 +23,7 @@ var pids = {}
var reboots = {} var reboots = {}
function buildRates () { function buildRates () {
var cryptoCoins = plugins.getCryptoCoins() var cryptoCodes = plugins.getcryptoCodes()
var config = plugins.getConfig() var config = plugins.getConfig()
var settings = config.exchanges.settings var settings = config.exchanges.settings
@ -31,9 +31,8 @@ function buildRates () {
var cashOutCommission = settings.fiatCommission || cashInCommission var cashOutCommission = settings.fiatCommission || cashInCommission
var rates = {} var rates = {}
cryptoCoins.forEach(function (coin) { cryptoCodes.forEach(function (cryptoCode) {
var cryptoCode = coin.unitCode var rate = plugins.getDeviceRate(cryptoCode).rates
var rate = plugins.getDeviceRate(coin).rates
rates[cryptoCode] = { rates[cryptoCode] = {
cashIn: rate.ask.times(cashInCommission), cashIn: rate.ask.times(cashInCommission),
cashOut: rate.bid.div(cashOutCommission) cashOut: rate.bid.div(cashOutCommission)
@ -44,12 +43,12 @@ function buildRates () {
} }
function buildBalances () { function buildBalances () {
var cryptoCoins = plugins.getCryptoCoins() var cryptoCodes = plugins.getcryptoCodes()
var balances = {} var balances = {}
cryptoCoins.forEach(function (coin) { cryptoCodes.forEach(function (cryptoCode) {
var balance = plugins.fiatBalance(coin) var balance = plugins.fiatBalance(cryptoCode)
balances[coin] = balance balances[cryptoCode] = balance
}) })
return balances return balances

View file

@ -1,5 +1,11 @@
- rethink scale names: is unit satoshi or btc? cryptoAtom, cryptoAtom
- cryptoCoin is record, not code
- specify crypto and fiat for trades - specify crypto and fiat for trades
- make sure ticker is in full coins - make sure ticker is in full coins
- getDeviceRate should return bignumber - getDeviceRate should return bignumber
- test with l-m
backwards compatibility:
- new l-m must be backwards compatible with old l-s
- parse out bignumber when loading in routes
- making a trade -- convert to units