fix up crypto services
This commit is contained in:
parent
e24da06a1b
commit
1b89ed5c76
9 changed files with 82 additions and 46 deletions
|
|
@ -32,7 +32,7 @@ function runOnce () {
|
||||||
const app = express()
|
const app = express()
|
||||||
const localApp = express()
|
const localApp = express()
|
||||||
|
|
||||||
return settingsLoader.load()
|
return settingsLoader.loadLatest()
|
||||||
.then(settings => {
|
.then(settings => {
|
||||||
poller.start(settings)
|
poller.start(settings)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
const configManager = require('./config-manager')
|
const configManager = require('./config-manager')
|
||||||
const settingsLoader = require('./settings-loader')
|
|
||||||
|
|
||||||
function noExchangeError (cryptoCode) {
|
function noExchangeError (cryptoCode) {
|
||||||
const err = new Error('No exchange plugin defined for: ' + cryptoCode)
|
const err = new Error('No exchange plugin defined for: ' + cryptoCode)
|
||||||
|
|
@ -8,15 +7,13 @@ function noExchangeError (cryptoCode) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
function lookupExchange (cryptoCode) {
|
function lookupExchange (settings, cryptoCode) {
|
||||||
const settings = settingsLoader.settings()
|
|
||||||
return configManager.cryptoScoped(cryptoCode, settings.config).exchange
|
return configManager.cryptoScoped(cryptoCode, settings.config).exchange
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchExchange (cryptoCode) {
|
function fetchExchange (settings, cryptoCode) {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const settings = settingsLoader.settings()
|
|
||||||
const plugin = lookupExchange(cryptoCode)
|
const plugin = lookupExchange(cryptoCode)
|
||||||
if (!plugin) throw noExchangeError(cryptoCode)
|
if (!plugin) throw noExchangeError(cryptoCode)
|
||||||
const account = settings.accounts[plugin]
|
const account = settings.accounts[plugin]
|
||||||
|
|
@ -26,18 +23,18 @@ function fetchExchange (cryptoCode) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function buy (cryptoAtoms, fiatCode, cryptoCode) {
|
function buy (settings, cryptoAtoms, fiatCode, cryptoCode) {
|
||||||
return fetchExchange(cryptoCode)
|
return fetchExchange(settings, cryptoCode)
|
||||||
.then(r => r.exchange.buy(r.account, cryptoAtoms, fiatCode, cryptoCode))
|
.then(r => r.exchange.buy(r.account, cryptoAtoms, fiatCode, cryptoCode))
|
||||||
}
|
}
|
||||||
|
|
||||||
function sell (cryptoAtoms, fiatCode, cryptoCode) {
|
function sell (settings, cryptoAtoms, fiatCode, cryptoCode) {
|
||||||
return fetchExchange(cryptoCode)
|
return fetchExchange(settings, cryptoCode)
|
||||||
.then(r => r.exchange.sell(r.account, cryptoAtoms, fiatCode, cryptoCode))
|
.then(r => r.exchange.sell(r.account, cryptoAtoms, fiatCode, cryptoCode))
|
||||||
}
|
}
|
||||||
|
|
||||||
function active (fiatCode, cryptoCode) {
|
function active (settings, fiatCode, cryptoCode) {
|
||||||
return !!lookupExchange(cryptoCode)
|
return !!lookupExchange(settings, cryptoCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,15 @@ function plugins (settings) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fetchCurrentConfigVersion () {
|
||||||
|
const sql = `select id from config_users
|
||||||
|
where type=$1
|
||||||
|
order by id desc
|
||||||
|
limit 1`
|
||||||
|
|
||||||
|
return db.one(sql, ['config'])
|
||||||
|
}
|
||||||
|
|
||||||
function pollQueries (deviceTime, deviceId, deviceRec) {
|
function pollQueries (deviceTime, deviceId, deviceRec) {
|
||||||
const config = configManager.machineScoped(deviceId, settings.config)
|
const config = configManager.machineScoped(deviceId, settings.config)
|
||||||
const fiatCode = config.fiatCurrency
|
const fiatCode = config.fiatCurrency
|
||||||
|
|
@ -95,22 +104,29 @@ function plugins (settings) {
|
||||||
config.bottomCashOutDenomination ]
|
config.bottomCashOutDenomination ]
|
||||||
const virtualCartridges = [config.virtualCashOutDenomination]
|
const virtualCartridges = [config.virtualCashOutDenomination]
|
||||||
|
|
||||||
const tickerPromises = cryptoCodes.map(c => ticker.getRates(fiatCode, c))
|
const tickerPromises = cryptoCodes.map(c => ticker.getRates(settings, fiatCode, c))
|
||||||
const balancePromises = cryptoCodes.map(wallet.balance)
|
const balancePromises = cryptoCodes.map(c => wallet.balance(settings, c))
|
||||||
const pingPromise = recordPing(deviceId, deviceTime, deviceRec)
|
const pingPromise = recordPing(deviceId, deviceTime, deviceRec)
|
||||||
|
const currentConfigVersionPromise = fetchCurrentConfigVersion()
|
||||||
|
|
||||||
const promises = [dbm.cartridgeCounts(deviceId), pingPromise].concat(tickerPromises, balancePromises)
|
const promises = [
|
||||||
|
dbm.cartridgeCounts(deviceId),
|
||||||
|
pingPromise,
|
||||||
|
currentConfigVersionPromise
|
||||||
|
].concat(tickerPromises, balancePromises)
|
||||||
|
|
||||||
return Promise.all(promises)
|
return Promise.all(promises)
|
||||||
.then(arr => {
|
.then(arr => {
|
||||||
const cartridgeCounts = arr[0]
|
const cartridgeCounts = arr[0]
|
||||||
const tickers = arr.slice(2, cryptoCodes.length + 2)
|
const currentConfigVersion = arr[2]
|
||||||
const balances = arr.slice(cryptoCodes.length + 2)
|
const tickers = arr.slice(3, cryptoCodes.length + 3)
|
||||||
|
const balances = arr.slice(cryptoCodes.length + 3)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
cartridges: buildCartridges(cartridges, virtualCartridges, cartridgeCounts),
|
cartridges: buildCartridges(cartridges, virtualCartridges, cartridgeCounts),
|
||||||
rates: buildRates(deviceId, tickers),
|
rates: buildRates(deviceId, tickers),
|
||||||
balances: buildBalances(deviceId, balances)
|
balances: buildBalances(deviceId, balances),
|
||||||
|
currentConfigVersion
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +135,7 @@ function plugins (settings) {
|
||||||
// a dbm unique dbm record in the table already.
|
// a dbm unique dbm record in the table already.
|
||||||
function executeTx (deviceId, tx) {
|
function executeTx (deviceId, tx) {
|
||||||
return dbm.addOutgoingTx(deviceId, tx)
|
return dbm.addOutgoingTx(deviceId, tx)
|
||||||
.then(() => wallet.sendCoins(tx.toAddress, tx.cryptoAtoms, tx.cryptoCode))
|
.then(() => wallet.sendCoins(settings, tx.toAddress, tx.cryptoAtoms, tx.cryptoCode))
|
||||||
.then(txHash => {
|
.then(txHash => {
|
||||||
const fee = null // Need to fill this out in plugins
|
const fee = null // Need to fill this out in plugins
|
||||||
const toSend = {cryptoAtoms: tx.cryptoAtoms, fiat: tx.fiat}
|
const toSend = {cryptoAtoms: tx.cryptoAtoms, fiat: tx.fiat}
|
||||||
|
|
@ -144,7 +160,7 @@ function plugins (settings) {
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const market = [fiatCode, cryptoCode].join('')
|
const market = [fiatCode, cryptoCode].join('')
|
||||||
|
|
||||||
if (!exchange.active(cryptoCode)) return
|
if (!exchange.active(settings, cryptoCode)) return
|
||||||
|
|
||||||
logger.debug('[%s] Pushing trade: %d', market, cryptoAtoms)
|
logger.debug('[%s] Pushing trade: %d', market, cryptoAtoms)
|
||||||
if (!tradesQueues[market]) tradesQueues[market] = []
|
if (!tradesQueues[market]) tradesQueues[market] = []
|
||||||
|
|
@ -187,7 +203,7 @@ function plugins (settings) {
|
||||||
serialNumber
|
serialNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
return wallet.newAddress(cryptoCode, info)
|
return wallet.newAddress(settings, cryptoCode, info)
|
||||||
.then(address => {
|
.then(address => {
|
||||||
const newTx = R.assoc('toAddress', address, tx)
|
const newTx = R.assoc('toAddress', address, tx)
|
||||||
|
|
||||||
|
|
@ -208,7 +224,10 @@ function plugins (settings) {
|
||||||
function fiatBalance (fiatCode, cryptoCode, deviceId) {
|
function fiatBalance (fiatCode, cryptoCode, deviceId) {
|
||||||
const config = configManager.scoped(cryptoCode, deviceId, settings.config)
|
const config = configManager.scoped(cryptoCode, deviceId, settings.config)
|
||||||
|
|
||||||
return Promise.all([ticker.getRates(fiatCode, cryptoCode), wallet.balance(cryptoCode)])
|
return Promise.all([
|
||||||
|
ticker.getRates(settings, fiatCode, cryptoCode),
|
||||||
|
wallet.balance(settings, cryptoCode)
|
||||||
|
])
|
||||||
.then(([rates, balanceRec]) => {
|
.then(([rates, balanceRec]) => {
|
||||||
const rawRate = rates.rates.ask
|
const rawRate = rates.rates.ask
|
||||||
const commission = (new BigNumber(config.cashInCommission).div(100)).plus(1)
|
const commission = (new BigNumber(config.cashInCommission).div(100)).plus(1)
|
||||||
|
|
@ -231,7 +250,7 @@ function plugins (settings) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function processTxStatus (tx) {
|
function processTxStatus (tx) {
|
||||||
return wallet.getStatus(tx.toAddress, tx.cryptoAtoms, tx.cryptoCode)
|
return wallet.getStatus(settings, tx.toAddress, tx.cryptoAtoms, tx.cryptoCode)
|
||||||
.then(res => dbm.updateTxStatus(tx, res.status))
|
.then(res => dbm.updateTxStatus(tx, res.status))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -355,7 +374,7 @@ function plugins (settings) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function executeTradesForMarket (settings, fiatCode, cryptoCode) {
|
function executeTradesForMarket (settings, fiatCode, cryptoCode) {
|
||||||
if (!exchange.active(cryptoCode)) return
|
if (!exchange.active(settings, cryptoCode)) return
|
||||||
|
|
||||||
const market = [fiatCode, cryptoCode].join('')
|
const market = [fiatCode, cryptoCode].join('')
|
||||||
logger.debug('[%s] checking for trades', market)
|
logger.debug('[%s] checking for trades', market)
|
||||||
|
|
@ -370,7 +389,7 @@ function plugins (settings) {
|
||||||
|
|
||||||
logger.debug('[%s] making a trade: %d', market, tradeEntry.cryptoAtoms.toString())
|
logger.debug('[%s] making a trade: %d', market, tradeEntry.cryptoAtoms.toString())
|
||||||
|
|
||||||
return exchange.buy(tradeEntry.cryptoAtoms, tradeEntry.fiatCode, tradeEntry.cryptoCode)
|
return exchange.buy(settings, tradeEntry.cryptoAtoms, tradeEntry.fiatCode, tradeEntry.cryptoCode)
|
||||||
.then(() => logger.debug('[%s] Successful trade.', market))
|
.then(() => logger.debug('[%s] Successful trade.', market))
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
tradesQueues[market].push(tradeEntry)
|
tradesQueues[market].push(tradeEntry)
|
||||||
|
|
@ -444,7 +463,7 @@ function plugins (settings) {
|
||||||
function sweepHD (row) {
|
function sweepHD (row) {
|
||||||
const cryptoCode = row.crypto_code
|
const cryptoCode = row.crypto_code
|
||||||
|
|
||||||
return wallet.sweep(row.hd_serial)
|
return wallet.sweep(settings, row.hd_serial)
|
||||||
.then(txHash => {
|
.then(txHash => {
|
||||||
if (txHash) {
|
if (txHash) {
|
||||||
logger.debug('[%s] Swept address with tx: %s', cryptoCode, txHash)
|
logger.debug('[%s] Swept address with tx: %s', cryptoCode, txHash)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
const R = require('ramda')
|
const R = require('ramda')
|
||||||
|
|
||||||
|
const db = require('./db')
|
||||||
const dbm = require('./postgresql_interface')
|
const dbm = require('./postgresql_interface')
|
||||||
const T = require('./time')
|
const T = require('./time')
|
||||||
const TRANSACTION_EXPIRATION = 2 * T.days
|
const TRANSACTION_EXPIRATION = 2 * T.days
|
||||||
|
|
@ -32,4 +33,8 @@ function fetchPhoneTx (phone) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {stateChange, fetchPhoneTx}
|
function updateDeviceConfigVersion (versionId) {
|
||||||
|
return db.none('update devices set user_config_id=$1', [versionId])
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {stateChange, fetchPhoneTx, updateDeviceConfigVersion}
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,8 @@ function poll (req, res, next) {
|
||||||
reboot,
|
reboot,
|
||||||
rates: results.rates,
|
rates: results.rates,
|
||||||
balances: results.balances,
|
balances: results.balances,
|
||||||
coins: config.cryptoCurrencies
|
coins: config.cryptoCurrencies,
|
||||||
|
configVersion: results.currentConfigVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.idVerificationEnabled) {
|
if (response.idVerificationEnabled) {
|
||||||
|
|
@ -421,13 +422,14 @@ function populateDeviceId (req, res, next) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function populateSettings (req, res, next) {
|
function populateSettings (req, res, next) {
|
||||||
const versionId = req.headers['config-version-id']
|
const versionId = req.headers['config-version']
|
||||||
if (!versionId) {
|
if (!versionId) {
|
||||||
logger.debug('No config-version-id header')
|
logger.debug('No config-version header')
|
||||||
return res.sendStatus(400)
|
return res.sendStatus(400)
|
||||||
}
|
}
|
||||||
|
|
||||||
settingsLoader.log(versionId)
|
settingsLoader.log(versionId)
|
||||||
.then(settings => { req.settings = settings })
|
.then(settings => { req.settings = settings })
|
||||||
|
.then(() => helpers.updateDeviceConfigVersion(versionId))
|
||||||
.catch(next)
|
.catch(next)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ const db = require('./db')
|
||||||
let settingsCache
|
let settingsCache
|
||||||
|
|
||||||
function load (versionId) {
|
function load (versionId) {
|
||||||
|
if (!versionId) throw new Error('versionId is required')
|
||||||
|
|
||||||
return Promise.all([loadConfig(versionId), loadAccounts()])
|
return Promise.all([loadConfig(versionId), loadAccounts()])
|
||||||
.then(([config, accounts]) => ({
|
.then(([config, accounts]) => ({
|
||||||
config,
|
config,
|
||||||
|
|
@ -23,7 +25,7 @@ function loadLatest (versionId) {
|
||||||
function loadConfig (versionId) {
|
function loadConfig (versionId) {
|
||||||
const sql = `select data
|
const sql = `select data
|
||||||
from user_config
|
from user_config
|
||||||
where versionId=$1 and type=$2`
|
where id=$1 and type=$2`
|
||||||
|
|
||||||
return db.oneOrNone(sql, [versionId, 'config'])
|
return db.oneOrNone(sql, [versionId, 'config'])
|
||||||
.then(row => row ? row.data.config : [])
|
.then(row => row ? row.data.config : [])
|
||||||
|
|
@ -33,7 +35,7 @@ function loadLatestConfig () {
|
||||||
const sql = `select data
|
const sql = `select data
|
||||||
from user_config
|
from user_config
|
||||||
where type=$1
|
where type=$1
|
||||||
order by versionId desc
|
order by id desc
|
||||||
limit 1`
|
limit 1`
|
||||||
|
|
||||||
return db.oneOrNone(sql, ['config'])
|
return db.oneOrNone(sql, ['config'])
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
const mem = require('mem')
|
const mem = require('mem')
|
||||||
const configManager = require('./config-manager')
|
const configManager = require('./config-manager')
|
||||||
const settingsLoader = require('./settings-loader')
|
|
||||||
|
|
||||||
const FETCH_INTERVAL = 10000
|
const FETCH_INTERVAL = 10000
|
||||||
function getRates (fiatCode, cryptoCode) {
|
function getRates (settings, fiatCode, cryptoCode) {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const settings = settingsLoader.settings()
|
|
||||||
const config = settings.config
|
const config = settings.config
|
||||||
const plugin = configManager.cryptoScoped(cryptoCode, config).ticker
|
const plugin = configManager.cryptoScoped(cryptoCode, config).ticker
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
const mem = require('mem')
|
const mem = require('mem')
|
||||||
const configManager = require('./config-manager')
|
const configManager = require('./config-manager')
|
||||||
const settingsLoader = require('./settings-loader')
|
|
||||||
|
|
||||||
const FETCH_INTERVAL = 5000
|
const FETCH_INTERVAL = 5000
|
||||||
|
|
||||||
function fetchWallet (cryptoCode) {
|
function fetchWallet (settings, cryptoCode) {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const settings = settingsLoader.settings()
|
|
||||||
const plugin = configManager.cryptoScoped(cryptoCode, settings.config).wallet
|
const plugin = configManager.cryptoScoped(cryptoCode, settings.config).wallet
|
||||||
const account = settings.accounts[plugin]
|
const account = settings.accounts[plugin]
|
||||||
const wallet = require('lamassu-' + plugin)
|
const wallet = require('lamassu-' + plugin)
|
||||||
|
|
@ -16,14 +14,14 @@ function fetchWallet (cryptoCode) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function balance (cryptoCode) {
|
function balance (settings, cryptoCode) {
|
||||||
return fetchWallet(cryptoCode)
|
return fetchWallet(settings, cryptoCode)
|
||||||
.then(r => r.wallet.balance(r.account, cryptoCode))
|
.then(r => r.wallet.balance(r.account, cryptoCode))
|
||||||
.then(balance => ({balance, timestamp: Date.now()}))
|
.then(balance => ({balance, timestamp: Date.now()}))
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendCoins (toAddress, cryptoAtoms, cryptoCode) {
|
function sendCoins (settings, toAddress, cryptoAtoms, cryptoCode) {
|
||||||
return fetchWallet(cryptoCode)
|
return fetchWallet(settings, cryptoCode)
|
||||||
.then(r => {
|
.then(r => {
|
||||||
return r.wallet.sendCoins(r.account, toAddress, cryptoAtoms, cryptoCode)
|
return r.wallet.sendCoins(r.account, toAddress, cryptoAtoms, cryptoCode)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
|
|
@ -33,13 +31,13 @@ function sendCoins (toAddress, cryptoAtoms, cryptoCode) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function newAddress (cryptoCode, info) {
|
function newAddress (settings, cryptoCode, info) {
|
||||||
return fetchWallet(cryptoCode)
|
return fetchWallet(settings, cryptoCode)
|
||||||
.then(r => r.wallet.newAddress(r.account, cryptoCode, info))
|
.then(r => r.wallet.newAddress(r.account, cryptoCode, info))
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStatus (toAddress, cryptoAtoms, cryptoCode) {
|
function getStatus (settings, toAddress, cryptoAtoms, cryptoCode) {
|
||||||
return fetchWallet(cryptoCode)
|
return fetchWallet(settings, cryptoCode)
|
||||||
.then(r => r.wallet.getStatus(r.account, toAddress, cryptoAtoms, cryptoCode))
|
.then(r => r.wallet.getStatus(r.account, toAddress, cryptoAtoms, cryptoCode))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
15
migrations/021-config-version-id.js
Normal file
15
migrations/021-config-version-id.js
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
var db = require('./db')
|
||||||
|
|
||||||
|
exports.up = function (next) {
|
||||||
|
var sql = [
|
||||||
|
'alter table devices add column user_config_id int',
|
||||||
|
`ALTER TABLE devices ADD CONSTRAINT user_config_id
|
||||||
|
FOREIGN KEY (user_config_id)
|
||||||
|
REFERENCES user_config (id)`
|
||||||
|
]
|
||||||
|
db.multi(sql, next)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.down = function (next) {
|
||||||
|
next()
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue