WIP
This commit is contained in:
parent
22c2acfe61
commit
e462359299
5 changed files with 52 additions and 104 deletions
|
|
@ -16,6 +16,13 @@ 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
|
||||||
|
|
@ -114,12 +121,13 @@ function loadPlugin (name, config) {
|
||||||
|
|
||||||
function loadOrConfigPlugin (pluginHandle, pluginType, cryptoCoin, currency,
|
function loadOrConfigPlugin (pluginHandle, pluginType, cryptoCoin, currency,
|
||||||
onChangeCallback) {
|
onChangeCallback) {
|
||||||
if (!cryptoCoin) cryptoCoin = 'any'
|
var cryptoCode = cryptoCoin ? cryptoCoin.unitCode : 'any'
|
||||||
var currentName = cryptoCoin === 'any' || cryptoCoin === 'BTC'
|
|
||||||
? cachedConfig.exchanges.plugins.current[pluginType]
|
|
||||||
: cachedConfig.exchanges.plugins.current[cryptoCoin][pluginType]
|
|
||||||
|
|
||||||
var pluginChanged = currentlyUsedPlugins[cryptoCoin][pluginType] !== currentName
|
var currentName = cryptoCode === 'any' || cryptoCode === 'BTC'
|
||||||
|
? cachedConfig.exchanges.plugins.current[pluginType]
|
||||||
|
: cachedConfig.exchanges.plugins.current[cryptoCode][pluginType]
|
||||||
|
|
||||||
|
var pluginChanged = currentlyUsedPlugins[cryptoCode][pluginType] !== currentName
|
||||||
|
|
||||||
if (!currentName) pluginHandle = null
|
if (!currentName) pluginHandle = null
|
||||||
else { // some plugins may be disabled
|
else { // some plugins may be disabled
|
||||||
|
|
@ -130,9 +138,9 @@ function loadOrConfigPlugin (pluginHandle, pluginType, cryptoCoin, currency,
|
||||||
if (pluginHandle && !pluginChanged) pluginHandle.config(pluginConfig)
|
if (pluginHandle && !pluginChanged) pluginHandle.config(pluginConfig)
|
||||||
else {
|
else {
|
||||||
pluginHandle = loadPlugin(currentName, pluginConfig)
|
pluginHandle = loadPlugin(currentName, pluginConfig)
|
||||||
currentlyUsedPlugins[cryptoCoin] = currentlyUsedPlugins[cryptoCoin] || {}
|
currentlyUsedPlugins[cryptoCode] = currentlyUsedPlugins[cryptoCode] || {}
|
||||||
currentlyUsedPlugins[cryptoCoin][pluginType] = currentName
|
currentlyUsedPlugins[cryptoCode][pluginType] = currentName
|
||||||
logger.debug('[%s] plugin(%s) loaded: %s', cryptoCoin, pluginType, pluginHandle.NAME ||
|
logger.debug('[%s] plugin(%s) loaded: %s', cryptoCode, pluginType, pluginHandle.NAME ||
|
||||||
currentName)
|
currentName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -149,29 +157,30 @@ 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']
|
cryptoCoins = config.exchanges.settings.coins || [BTC_COIN]
|
||||||
|
|
||||||
cryptoCoins.forEach(function (cryptoCoin) {
|
cryptoCoins.forEach(function (cryptoCoin) {
|
||||||
// TICKER [required] configure (or load)
|
// TICKER [required] configure (or load)
|
||||||
|
var cryptoCode = cryptoCoin.unitCode
|
||||||
loadOrConfigPlugin(
|
loadOrConfigPlugin(
|
||||||
tickerPlugins[cryptoCoin],
|
tickerPlugins[cryptoCode],
|
||||||
'ticker',
|
'ticker',
|
||||||
cryptoCoin,
|
cryptoCoin,
|
||||||
deviceCurrency, // device currency
|
deviceCurrency, // device currency
|
||||||
function onTickerChange (newTicker) {
|
function onTickerChange (newTicker) {
|
||||||
tickerPlugins[cryptoCoin] = newTicker
|
tickerPlugins[cryptoCode] = newTicker
|
||||||
pollRate(cryptoCoin)
|
pollRate(cryptoCoin)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// WALLET [required] configure (or load)
|
// WALLET [required] configure (or load)
|
||||||
loadOrConfigPlugin(
|
loadOrConfigPlugin(
|
||||||
walletPlugins[cryptoCoin],
|
walletPlugins[cryptoCode],
|
||||||
'transfer',
|
'transfer',
|
||||||
cryptoCoin,
|
cryptoCoin,
|
||||||
null,
|
null,
|
||||||
function onWalletChange (newWallet) {
|
function onWalletChange (newWallet) {
|
||||||
walletPlugins[cryptoCoin] = newWallet
|
walletPlugins[cryptoCode] = newWallet
|
||||||
pollBalance(cryptoCoin)
|
pollBalance(cryptoCoin)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -240,9 +249,10 @@ exports.pollQueries = function pollQueries (session, cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function _sendCoins (toAddress, cryptoUnits, cryptoCoin, cb) {
|
function _sendCoins (toAddress, cryptoUnits, cryptoCoin, cb) {
|
||||||
var walletPlugin = walletPlugins[cryptoCoin]
|
var cryptoCode = cryptoCoin.unitCode
|
||||||
|
var walletPlugin = walletPlugins[cryptoCode]
|
||||||
var transactionFee = cachedConfig.exchanges.settings.transactionFee
|
var transactionFee = cachedConfig.exchanges.settings.transactionFee
|
||||||
if (cryptoCoin === 'BTC') {
|
if (cryptoCode === 'BTC') {
|
||||||
walletPlugin.sendBitcoins(toAddress, cryptoUnits, transactionFee, cb)
|
walletPlugin.sendBitcoins(toAddress, cryptoUnits, transactionFee, cb)
|
||||||
} else {
|
} else {
|
||||||
walletPlugin.sendCoins(toAddress, cryptoUnits, cryptoCoin, transactionFee, cb)
|
walletPlugin.sendCoins(toAddress, cryptoUnits, cryptoCoin, transactionFee, cb)
|
||||||
|
|
@ -350,11 +360,10 @@ exports.cashOut = function cashOut (session, tx, cb) {
|
||||||
account: 'deposit'
|
account: 'deposit'
|
||||||
}
|
}
|
||||||
|
|
||||||
var cryptoCoin = tx.coin
|
var cryptoCoin = tx.coin || BTC_COIN
|
||||||
? tx.coin.unitCode
|
var cryptoCode = cryptoCoin.unitCode
|
||||||
: 'BTC'
|
|
||||||
|
|
||||||
var walletPlugin = walletPlugins[cryptoCoin]
|
var walletPlugin = walletPlugins[cryptoCode]
|
||||||
|
|
||||||
walletPlugin.newAddress(tmpInfo, function (err, address) {
|
walletPlugin.newAddress(tmpInfo, function (err, address) {
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
|
|
@ -372,9 +381,10 @@ exports.dispenseAck = function dispenseAck (session, rec) {
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.fiatBalance = function fiatBalance (cryptoCoin) {
|
exports.fiatBalance = function fiatBalance (cryptoCoin) {
|
||||||
|
var cryptoCode = cryptoCoin.unitCode
|
||||||
var rawRate = exports.getDeviceRate(cryptoCoin).rates.ask
|
var rawRate = exports.getDeviceRate(cryptoCoin).rates.ask
|
||||||
var commission = cachedConfig.exchanges.settings.commission
|
var commission = cachedConfig.exchanges.settings.commission
|
||||||
var lastBalance = lastBalances[cryptoCoin]
|
var lastBalance = lastBalances[cryptoCode]
|
||||||
|
|
||||||
if (!rawRate || !lastBalance) return null
|
if (!rawRate || !lastBalance) return null
|
||||||
|
|
||||||
|
|
@ -432,9 +442,10 @@ function stopTrader () {
|
||||||
}
|
}
|
||||||
|
|
||||||
function pollBalance (cryptoCoin, cb) {
|
function pollBalance (cryptoCoin, cb) {
|
||||||
logger.debug('[%s] collecting balance', cryptoCoin)
|
var cryptoCode = cryptoCoin.unitCode
|
||||||
|
logger.debug('[%s] collecting balance', cryptoCode)
|
||||||
|
|
||||||
var walletPlugin = walletPlugins[cryptoCoin]
|
var walletPlugin = walletPlugins[cryptoCode]
|
||||||
|
|
||||||
walletPlugin.balance(function (err, balance) {
|
walletPlugin.balance(function (err, balance) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
@ -442,22 +453,23 @@ function pollBalance (cryptoCoin, cb) {
|
||||||
return cb && cb(err)
|
return cb && cb(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug('[%s] Balance update:', cryptoCoin, balance)
|
logger.debug('[%s] Balance update:', cryptoCode, balance)
|
||||||
balance.timestamp = Date.now()
|
balance.timestamp = Date.now()
|
||||||
lastBalances[cryptoCoin] = balance
|
lastBalances[cryptoCode] = balance
|
||||||
|
|
||||||
return cb && cb(null, lastBalances)
|
return cb && cb(null, lastBalances)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function pollRate (cryptoCoin, cb) {
|
function pollRate (cryptoCoin, cb) {
|
||||||
logger.debug('[%s] polling for rates (%s)', cryptoCoin, tickerPlugin.NAME)
|
var cryptoCode = cryptoCoin.unitCode
|
||||||
var tickerPlugin = tickerPlugins[cryptoCoin]
|
logger.debug('[%s] polling for rates (%s)', cryptoCode, tickerPlugin.NAME)
|
||||||
|
var tickerPlugin = tickerPlugins[cryptoCode]
|
||||||
|
|
||||||
var currencies = deviceCurrency
|
var currencies = deviceCurrency
|
||||||
if (typeof currencies === 'string') currencies = [currencies]
|
if (typeof currencies === 'string') currencies = [currencies]
|
||||||
|
|
||||||
var tickerF = cryptoCoin === '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, cryptoCoin)
|
||||||
|
|
||||||
|
|
@ -469,7 +481,7 @@ function pollRate (cryptoCoin, cb) {
|
||||||
|
|
||||||
logger.debug('got rates: %j', resRates)
|
logger.debug('got rates: %j', resRates)
|
||||||
resRates.timestamp = new Date()
|
resRates.timestamp = new Date()
|
||||||
lastRates[cryptoCoin] = resRates
|
lastRates[cryptoCode] = resRates
|
||||||
|
|
||||||
return cb && cb(null, lastRates)
|
return cb && cb(null, lastRates)
|
||||||
})
|
})
|
||||||
|
|
@ -480,16 +492,18 @@ function pollRate (cryptoCoin, cb) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.getDeviceRate = function getDeviceRate (cryptoCoin) {
|
exports.getDeviceRate = function getDeviceRate (cryptoCoin) {
|
||||||
if (!lastRates[cryptoCoin]) return null
|
var cryptoCode = cryptoCoin.unitCode
|
||||||
|
if (!lastRates[cryptoCode]) return null
|
||||||
|
|
||||||
var lastRate = lastRates[cryptoCoin]
|
var lastRate = lastRates[cryptoCode]
|
||||||
if (!lastRate) return null
|
if (!lastRate) return null
|
||||||
|
|
||||||
return lastRate[deviceCurrency]
|
return lastRate[deviceCurrency]
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getBalance = function getBalance (cryptoCoin) {
|
exports.getBalance = function getBalance (cryptoCoin) {
|
||||||
var lastBalance = lastBalances[cryptoCoin]
|
var cryptoCode = cryptoCoin.unitCode
|
||||||
|
var lastBalance = lastBalances[cryptoCode]
|
||||||
if (!lastBalance) return null
|
if (!lastBalance) return null
|
||||||
|
|
||||||
return lastBalance.transferBalance
|
return lastBalance.transferBalance
|
||||||
|
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
require('es6-promise').polyfill()
|
|
||||||
var axios = require('axios')
|
|
||||||
var _ = require('lodash')
|
|
||||||
|
|
||||||
var BigNumber = require('bignumber.js')
|
|
||||||
BigNumber.config({DECIMAL_PLACES: 40})
|
|
||||||
|
|
||||||
exports.NAME = 'Kraken'
|
|
||||||
exports.SUPPORTED_MODULES = ['ticker']
|
|
||||||
|
|
||||||
exports.config = function config (localConfig) {
|
|
||||||
}
|
|
||||||
|
|
||||||
function findCurrency (fxRates, currency) {
|
|
||||||
return new BigNumber(_.find(fxRates, function (r) { return r.code === currency }).rate)
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.ticker = function ticker (currencies, cryptoCoin, callback) {
|
|
||||||
return axios.get('https://bitpay.com/api/rates')
|
|
||||||
.then(function (response) {
|
|
||||||
var fxRates = response.data
|
|
||||||
|
|
||||||
return axios.get('https://api.kraken.com/0/public/Ticker?pair=ETHUSD')
|
|
||||||
.then(function (response2) {
|
|
||||||
var usdRate = findCurrency(fxRates, 'USD')
|
|
||||||
var rates = response2.data.result.XETHZUSD
|
|
||||||
var res = {}
|
|
||||||
var cryptoCoinFactor = new BigNumber(10).pow(cryptoCoin.unitScale)
|
|
||||||
|
|
||||||
currencies.forEach(function (currency) {
|
|
||||||
var fxRate = findCurrency(fxRates, currency).div(usdRate)
|
|
||||||
res[currency] = {
|
|
||||||
ask: fxRate.times(rates.a[0]).div(cryptoCoinFactor),
|
|
||||||
bid: fxRate.times(rates.b[0]).div(cryptoCoinFactor)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
callback(null, res)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.catch(callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.ticker(['USD', 'ILS', 'EUR'], {unitScale: 18}, function (err, res) {
|
|
||||||
if (err) return console.log(err.stack)
|
|
||||||
console.log(JSON.stringify(res, null, 2))
|
|
||||||
})
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
var Web3 = require('web3')
|
|
||||||
|
|
||||||
var web3 = new Web3()
|
|
||||||
|
|
||||||
if (!web3.isConnected()) {
|
|
||||||
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: it's still called sendBitcoins for backwards compatibility, but this
|
|
||||||
// is for any currency
|
|
||||||
exports.sendBitcoins = function sendBitcoins (address, satoshis, fee, callback) {
|
|
||||||
web3.eth.sendTransaction({
|
|
||||||
to: address,
|
|
||||||
value: satoshis
|
|
||||||
}, callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.balance = function balance (cb) {
|
|
||||||
var coinbase = web3.eth.coinbase
|
|
||||||
web3.eth.getBalance(coinbase, 'pending', cb)
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.newAddress = function newAddress (info, callback) {
|
|
||||||
throw new Error('Not implemented')
|
|
||||||
}
|
|
||||||
|
|
@ -32,8 +32,9 @@ function buildRates () {
|
||||||
|
|
||||||
var rates = {}
|
var rates = {}
|
||||||
cryptoCoins.forEach(function (coin) {
|
cryptoCoins.forEach(function (coin) {
|
||||||
|
var cryptoCode = coin.unitCode
|
||||||
var rate = plugins.getDeviceRate(coin).rates
|
var rate = plugins.getDeviceRate(coin).rates
|
||||||
rates[coin] = {
|
rates[cryptoCode] = {
|
||||||
cashIn: rate.ask.times(cashInCommission),
|
cashIn: rate.ask.times(cashInCommission),
|
||||||
cashOut: rate.bid.div(cashOutCommission)
|
cashOut: rate.bid.div(cashOutCommission)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
todo.txt
Normal file
5
todo.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
- specify crypto and fiat for trades
|
||||||
|
- make sure ticker is in full coins
|
||||||
|
- rethink scale names: is unit satoshi or btc?
|
||||||
|
- cryptoCoin is record, not code
|
||||||
|
- getDeviceRate should return bignumber
|
||||||
Loading…
Add table
Add a link
Reference in a new issue