improve config loading; remove debug
This commit is contained in:
parent
5f0b70ca42
commit
614c64646a
15 changed files with 198 additions and 193 deletions
|
|
@ -11,6 +11,7 @@ const settingsLoader = require('../settings-loader')
|
|||
const db = require('../db')
|
||||
const options = require('../options')
|
||||
const configManager = require('../config-manager')
|
||||
const configValidate = require('../config-validate')
|
||||
|
||||
const machines = require('./machines')
|
||||
|
||||
|
|
@ -38,15 +39,6 @@ function allScopes (cryptoScopes, machineScopes) {
|
|||
return scopes
|
||||
}
|
||||
|
||||
function allCryptoScopes (cryptos, cryptoScope) {
|
||||
const cryptoScopes = []
|
||||
|
||||
if (cryptoScope === 'global' || cryptoScope === 'both') cryptoScopes.push('global')
|
||||
if (cryptoScope === 'specific' || cryptoScope === 'both') cryptos.forEach(r => cryptoScopes.push(r))
|
||||
|
||||
return cryptoScopes
|
||||
}
|
||||
|
||||
function allMachineScopes (machineList, machineScope) {
|
||||
const machineScopes = []
|
||||
|
||||
|
|
@ -56,43 +48,6 @@ function allMachineScopes (machineList, machineScope) {
|
|||
return machineScopes
|
||||
}
|
||||
|
||||
function satisfiesRequire (config, cryptos, machineList, field, refFields) {
|
||||
const fieldCode = field.code
|
||||
|
||||
const scopes = allScopes(
|
||||
allCryptoScopes(cryptos, field.cryptoScope),
|
||||
allMachineScopes(machineList, field.machineScope)
|
||||
)
|
||||
|
||||
return scopes.every(scope => {
|
||||
const isEnabled = () => refFields.some(refField => {
|
||||
return isScopeEnabled(config, cryptos, machineList, refField, scope)
|
||||
})
|
||||
|
||||
const isBlank = () => R.isNil(configManager.scopedValue(scope[0], scope[1], fieldCode, config))
|
||||
const isRequired = refFields.length === 0 || isEnabled()
|
||||
|
||||
return isRequired ? !isBlank() : true
|
||||
})
|
||||
}
|
||||
|
||||
function isScopeEnabled (config, cryptos, machineList, refField, scope) {
|
||||
const [cryptoScope, machineScope] = scope
|
||||
const candidateCryptoScopes = cryptoScope === 'global'
|
||||
? allCryptoScopes(cryptos, refField.cryptoScope)
|
||||
: [cryptoScope]
|
||||
|
||||
const candidateMachineScopes = machineScope === 'global'
|
||||
? allMachineScopes(machineList, refField.machineScope)
|
||||
: [ machineScope ]
|
||||
|
||||
const allRefCandidateScopes = allScopes(candidateCryptoScopes, candidateMachineScopes)
|
||||
const getFallbackValue = scope => configManager.scopedValue(scope[0], scope[1], refField.code, config)
|
||||
const values = allRefCandidateScopes.map(getFallbackValue)
|
||||
|
||||
return values.some(r => r)
|
||||
}
|
||||
|
||||
function getCryptos (config, machineList) {
|
||||
const scopes = allScopes(['global'], allMachineScopes(machineList, 'both'))
|
||||
const scoped = scope => configManager.scopedValue(scope[0], scope[1], 'cryptoCurrencies', config)
|
||||
|
|
@ -112,60 +67,9 @@ function getField (schema, group, fieldCode) {
|
|||
const fetchMachines = () => machines.getMachines()
|
||||
.then(machineList => machineList.map(r => r.deviceId))
|
||||
|
||||
function validateFieldParameter (value, validator) {
|
||||
switch (validator.code) {
|
||||
case 'required':
|
||||
return true // We don't validate this here
|
||||
case 'min':
|
||||
return value >= validator.min
|
||||
case 'max':
|
||||
return value <= validator.max
|
||||
default:
|
||||
throw new Error('Unknown validation type: ' + validator.code)
|
||||
}
|
||||
}
|
||||
|
||||
// Validates specific field properties other than required property
|
||||
function enforceValidConfigParameters (fieldInstances) {
|
||||
return fetchSchema()
|
||||
.then(schema => {
|
||||
const pickField = fieldCode => schema.fields.find(r => r.code === fieldCode)
|
||||
|
||||
return fieldInstances.every(fieldInstance => {
|
||||
const fieldCode = fieldInstance.fieldLocator.code
|
||||
const field = pickField(fieldCode)
|
||||
const fieldValue = fieldInstance.fieldValue
|
||||
|
||||
const isValid = field.fieldValidation
|
||||
.every(validator => validateFieldParameter(fieldValue.value, validator))
|
||||
|
||||
if (isValid) return true
|
||||
|
||||
throw new Error('Invalid config value')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function validateConfig (config) {
|
||||
return Promise.all([fetchSchema(), fetchMachines()])
|
||||
.then(([schema, machineList]) => {
|
||||
const cryptos = getCryptos(config, machineList)
|
||||
return schema.groups.filter(group => {
|
||||
return group.fields.some(fieldCode => {
|
||||
const field = getField(schema, group, fieldCode)
|
||||
if (!field.fieldValidation.find(r => r.code === 'required')) return false
|
||||
|
||||
const refFields = (field.enabledIf || []).map(R.curry(getField)(schema, null))
|
||||
return !satisfiesRequire(config, cryptos, machineList, field, refFields)
|
||||
})
|
||||
})
|
||||
})
|
||||
.then(arr => arr.map(r => r.code))
|
||||
}
|
||||
|
||||
function validateCurrentConfig () {
|
||||
return fetchConfig()
|
||||
.then(validateConfig)
|
||||
.then(configValidate.validateRequires)
|
||||
}
|
||||
|
||||
function fetchConfigGroup (code) {
|
||||
|
|
@ -245,6 +149,7 @@ function fetchData () {
|
|||
{code: 'bitgo', display: 'BitGo', class: 'wallet', cryptos: ['BTC']},
|
||||
{code: 'geth', display: 'geth', class: 'wallet', cryptos: ['ETH']},
|
||||
{code: 'mock-wallet', display: 'Mock wallet', class: 'wallet', cryptos: ['BTC', 'ETH']},
|
||||
{code: 'no-exchange', display: 'No exchange', class: 'exchange', cryptos: ['BTC', 'ETH']},
|
||||
{code: 'mock-exchange', display: 'Mock exchange', class: 'exchange', cryptos: ['BTC', 'ETH']},
|
||||
{code: 'mock-sms', display: 'Mock SMS', class: 'sms'},
|
||||
{code: 'mock-id-verify', display: 'Mock ID verifier', class: 'idVerifier'},
|
||||
|
|
@ -258,7 +163,7 @@ function fetchData () {
|
|||
function saveConfigGroup (results) {
|
||||
if (results.values.length === 0) return fetchConfigGroup(results.groupCode)
|
||||
|
||||
return enforceValidConfigParameters(results.values)
|
||||
return configValidate.ensureConstraints(results.values)
|
||||
.then(fetchConfig)
|
||||
.then(oldValues => {
|
||||
results.values.forEach(newValue => {
|
||||
|
|
|
|||
|
|
@ -45,19 +45,26 @@ function status () {
|
|||
const lastPing = statusRow && age.humanize()
|
||||
|
||||
return settingsLoader.loadLatest()
|
||||
.catch(() => null)
|
||||
.then(settings => {
|
||||
return ticker.getRates(settings, 'USD', 'BTC')
|
||||
.then(ratesRec => {
|
||||
const rates = [{
|
||||
crypto: 'BTC',
|
||||
bid: parseFloat(ratesRec.rates.bid),
|
||||
ask: parseFloat(ratesRec.rates.ask)
|
||||
}]
|
||||
return {up, lastPing, rates, machineStatus}
|
||||
})
|
||||
.catch(() => ({up, lastPing, rates: [], machineStatus}))
|
||||
return getRates(settings)
|
||||
.then(rates => ({up, lastPing, rates, machineStatus}))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getRates (settings) {
|
||||
if (!settings) return Promise.resolve([])
|
||||
|
||||
return ticker.getRates(settings, 'USD', 'BTC')
|
||||
.then(ratesRec => {
|
||||
return [{
|
||||
crypto: 'BTC',
|
||||
bid: parseFloat(ratesRec.rates.bid),
|
||||
ask: parseFloat(ratesRec.rates.ask)
|
||||
}]
|
||||
})
|
||||
.catch(() => [])
|
||||
}
|
||||
|
||||
module.exports = {status}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ const argv = require('minimist')(process.argv.slice(2))
|
|||
const routes = require('./routes')
|
||||
const logger = require('./logger')
|
||||
const poller = require('./poller')
|
||||
const verifySchema = require('./verify-schema')
|
||||
const settingsLoader = require('./settings-loader')
|
||||
const options = require('./options')
|
||||
|
||||
|
|
@ -33,8 +32,7 @@ function run () {
|
|||
}
|
||||
|
||||
function runOnce () {
|
||||
return verifySchema.valid()
|
||||
.then(() => settingsLoader.loadLatest())
|
||||
return settingsLoader.loadLatest()
|
||||
.then(settings => {
|
||||
poller.start(settings)
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ function post (tx, pi) {
|
|||
const isolationLevel = pgp.txMode.isolationLevel
|
||||
const tmSRD = new TransactionMode({tiLevel: isolationLevel.serializable})
|
||||
|
||||
console.log('DEBUG502: %j', tx)
|
||||
function transaction (t) {
|
||||
const sql = 'select * from cash_in_txs where id=$1'
|
||||
const sql2 = 'select * from bills where cash_in_txs_id=$1'
|
||||
|
|
@ -131,7 +130,6 @@ function insertNewBills (billRows, tx) {
|
|||
|
||||
function upsert (oldTx, tx) {
|
||||
if (!oldTx) {
|
||||
console.log('DEBUG500: %j', tx)
|
||||
return insert(tx)
|
||||
.then(newTx => [oldTx, newTx])
|
||||
}
|
||||
|
|
@ -160,9 +158,7 @@ function update (tx, changes) {
|
|||
}
|
||||
|
||||
function registerTrades (pi, txVector) {
|
||||
console.log('DEBUG400')
|
||||
const newBills = _.last(txVector)
|
||||
console.log('DEBUG401: %j', newBills)
|
||||
_.forEach(bill => pi.buy(bill), newBills)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ function httpError (msg, code) {
|
|||
}
|
||||
|
||||
function post (tx, pi) {
|
||||
console.log('DEBUG101: %j', tx)
|
||||
const TransactionMode = pgp.txMode.TransactionMode
|
||||
const isolationLevel = pgp.txMode.isolationLevel
|
||||
const tmSRD = new TransactionMode({tiLevel: isolationLevel.serializable})
|
||||
|
|
@ -104,7 +103,6 @@ function logAction (action, _rec, tx) {
|
|||
const rec = _.assign(_rec, {action, tx_id: tx.id, redeem: !!tx.redeem})
|
||||
const sql = pgp.helpers.insert(rec, null, 'cash_out_actions')
|
||||
|
||||
console.log('DEBUG110: %j', sql)
|
||||
return db.none(sql)
|
||||
.then(_.constant(tx))
|
||||
}
|
||||
|
|
@ -204,9 +202,7 @@ function update (tx, changes) {
|
|||
}
|
||||
|
||||
function nextHd (isHd, tx) {
|
||||
console.log('DEBUG160: %s', isHd)
|
||||
if (!isHd) return Promise.resolve(tx)
|
||||
console.log('DEBUG161: %s', isHd)
|
||||
|
||||
return db.one("select nextval('hd_indices_seq') as hd_index")
|
||||
.then(row => _.set('hdIndex', row.hd_index, tx))
|
||||
|
|
@ -257,9 +253,7 @@ function preProcess (oldTx, newTx, pi) {
|
|||
return logAction(updatedTx.status, rec, updatedTx)
|
||||
}
|
||||
|
||||
console.log('DEBUG120: %j', [oldTx, updatedTx])
|
||||
if (!oldTx.dispenseConfirmed && updatedTx.dispenseConfirmed) {
|
||||
console.log('DEBUG121')
|
||||
return logDispense(updatedTx)
|
||||
.then(updateCassettes(updatedTx))
|
||||
}
|
||||
|
|
@ -280,7 +274,6 @@ function postProcess (txVector, pi) {
|
|||
const [oldTx, newTx] = txVector
|
||||
|
||||
if (newTx.dispense && !oldTx.dispense) {
|
||||
console.log('DEBUG130')
|
||||
return pi.buildCassettes()
|
||||
.then(cassettes => {
|
||||
pi.sell(newTx)
|
||||
|
|
|
|||
150
lib/config-validate.js
Normal file
150
lib/config-validate.js
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
const _ = require('lodash/fp')
|
||||
|
||||
const configManager = require('./config-manager')
|
||||
const machines = require('./admin/machines')
|
||||
const schema = require('../lamassu-schema.json')
|
||||
|
||||
function allScopes (cryptoScopes, machineScopes) {
|
||||
const scopes = []
|
||||
cryptoScopes.forEach(c => {
|
||||
machineScopes.forEach(m => scopes.push([c, m]))
|
||||
})
|
||||
|
||||
return scopes
|
||||
}
|
||||
|
||||
function allCryptoScopes (cryptos, cryptoScope) {
|
||||
const cryptoScopes = []
|
||||
|
||||
if (cryptoScope === 'global' || cryptoScope === 'both') cryptoScopes.push('global')
|
||||
if (cryptoScope === 'specific' || cryptoScope === 'both') cryptos.forEach(r => cryptoScopes.push(r))
|
||||
|
||||
return cryptoScopes
|
||||
}
|
||||
|
||||
function allMachineScopes (machineList, machineScope) {
|
||||
const machineScopes = []
|
||||
|
||||
if (machineScope === 'global' || machineScope === 'both') machineScopes.push('global')
|
||||
if (machineScope === 'specific' || machineScope === 'both') machineList.forEach(r => machineScopes.push(r))
|
||||
|
||||
return machineScopes
|
||||
}
|
||||
|
||||
function satisfiesRequire (config, cryptos, machineList, field, refFields) {
|
||||
const fieldCode = field.code
|
||||
|
||||
const scopes = allScopes(
|
||||
allCryptoScopes(cryptos, field.cryptoScope),
|
||||
allMachineScopes(machineList, field.machineScope)
|
||||
)
|
||||
|
||||
return scopes.every(scope => {
|
||||
const isEnabled = () => refFields.some(refField => {
|
||||
return isScopeEnabled(config, cryptos, machineList, refField, scope)
|
||||
})
|
||||
|
||||
const isBlank = () => _.isNil(configManager.scopedValue(scope[0], scope[1], fieldCode, config))
|
||||
const isRequired = refFields.length === 0 || isEnabled()
|
||||
|
||||
return isRequired ? !isBlank() : true
|
||||
})
|
||||
}
|
||||
|
||||
function isScopeEnabled (config, cryptos, machineList, refField, scope) {
|
||||
const [cryptoScope, machineScope] = scope
|
||||
const candidateCryptoScopes = cryptoScope === 'global'
|
||||
? allCryptoScopes(cryptos, refField.cryptoScope)
|
||||
: [cryptoScope]
|
||||
|
||||
const candidateMachineScopes = machineScope === 'global'
|
||||
? allMachineScopes(machineList, refField.machineScope)
|
||||
: [ machineScope ]
|
||||
|
||||
const allRefCandidateScopes = allScopes(candidateCryptoScopes, candidateMachineScopes)
|
||||
const getFallbackValue = scope => configManager.scopedValue(scope[0], scope[1], refField.code, config)
|
||||
const values = allRefCandidateScopes.map(getFallbackValue)
|
||||
|
||||
return values.some(r => r)
|
||||
}
|
||||
|
||||
function getCryptos (config, machineList) {
|
||||
const scopes = allScopes(['global'], allMachineScopes(machineList, 'both'))
|
||||
const scoped = scope => configManager.scopedValue(scope[0], scope[1], 'cryptoCurrencies', config)
|
||||
return scopes.reduce((acc, scope) => _.union(acc, scoped(scope)), [])
|
||||
}
|
||||
|
||||
function getGroup (fieldCode) {
|
||||
return _.find(group => _.includes(fieldCode, group.fields), schema.groups)
|
||||
}
|
||||
|
||||
function getField (group, fieldCode) {
|
||||
if (!group) group = getGroup(fieldCode)
|
||||
const field = _.find(_.matchesProperty('code', fieldCode), schema.fields)
|
||||
return _.merge(_.pick(['cryptoScope', 'machineScope'], group), field)
|
||||
}
|
||||
|
||||
const fetchMachines = () => machines.getMachines()
|
||||
.then(machineList => machineList.map(r => r.deviceId))
|
||||
|
||||
function validateFieldParameter (value, validator) {
|
||||
switch (validator.code) {
|
||||
case 'required':
|
||||
return true // We don't validate this here
|
||||
case 'min':
|
||||
return value >= validator.min
|
||||
case 'max':
|
||||
return value <= validator.max
|
||||
default:
|
||||
throw new Error('Unknown validation type: ' + validator.code)
|
||||
}
|
||||
}
|
||||
|
||||
function ensureConstraints (config) {
|
||||
const pickField = fieldCode => schema.fields.find(r => r.code === fieldCode)
|
||||
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
config.every(fieldInstance => {
|
||||
const fieldCode = fieldInstance.fieldLocator.code
|
||||
const field = pickField(fieldCode)
|
||||
const fieldValue = fieldInstance.fieldValue
|
||||
|
||||
const isValid = field.fieldValidation
|
||||
.every(validator => validateFieldParameter(fieldValue.value, validator))
|
||||
|
||||
if (isValid) return true
|
||||
throw new Error('Invalid config value')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function validateRequires (config) {
|
||||
return fetchMachines()
|
||||
.then(machineList => {
|
||||
const cryptos = getCryptos(config, machineList)
|
||||
|
||||
return schema.groups.filter(group => {
|
||||
return group.fields.some(fieldCode => {
|
||||
const field = getField(group, fieldCode)
|
||||
if (!field.fieldValidation.find(r => r.code === 'required')) return false
|
||||
|
||||
const refFields = _.map(_.partial(getField, null), field.enabledIf)
|
||||
return !satisfiesRequire(config, cryptos, machineList, field, refFields)
|
||||
})
|
||||
})
|
||||
})
|
||||
.then(arr => arr.map(r => r.code))
|
||||
}
|
||||
|
||||
function validate (config) {
|
||||
return Promise.resolve()
|
||||
.then(() => ensureConstraints(config))
|
||||
.then(() => validateRequires(config))
|
||||
.then(arr => {
|
||||
if (arr.length === 0) return config
|
||||
throw new Error('Invalid configuration')
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {validate, ensureConstraints, validateRequires}
|
||||
|
|
@ -2,13 +2,16 @@ const configManager = require('./config-manager')
|
|||
const ph = require('./plugin-helper')
|
||||
|
||||
function lookupExchange (settings, cryptoCode) {
|
||||
return configManager.cryptoScoped(cryptoCode, settings.config).exchange
|
||||
const exchange = configManager.cryptoScoped(cryptoCode, settings.config).exchange
|
||||
if (exchange === 'no-exchange') return null
|
||||
return exchange
|
||||
}
|
||||
|
||||
function fetchExchange (settings, cryptoCode) {
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
const plugin = lookupExchange(settings, cryptoCode)
|
||||
if (!plugin) throw new Error('No exchange set')
|
||||
const exchange = ph.load(ph.EXCHANGE, plugin)
|
||||
const account = settings.accounts[plugin]
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ function sendNoAlerts (plugins) {
|
|||
function checkNotification (plugins) {
|
||||
return checkStatus(plugins)
|
||||
.then(alertRec => {
|
||||
console.log('DEBUG445: %j', alertRec)
|
||||
const currentAlertFingerprint = buildAlertFingerprint(alertRec)
|
||||
if (!currentAlertFingerprint) {
|
||||
const inAlert = !!alertFingerprint
|
||||
|
|
@ -80,7 +79,6 @@ function checkNotification (plugins) {
|
|||
alertFingerprint = currentAlertFingerprint
|
||||
lastAlertTime = Date.now()
|
||||
|
||||
console.log('DEBUG446: %j', rec)
|
||||
return plugins.sendMessage(rec)
|
||||
})
|
||||
.then(results => {
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ function plugins (settings, deviceId) {
|
|||
function fetchCurrentConfigVersion () {
|
||||
const sql = `select id from user_config
|
||||
where type=$1
|
||||
and valid
|
||||
order by id desc
|
||||
limit 1`
|
||||
|
||||
|
|
@ -278,9 +279,7 @@ function plugins (settings, deviceId) {
|
|||
|
||||
const market = [fiatCode, cryptoCode].join('')
|
||||
|
||||
console.log('DEBUG333')
|
||||
if (!exchange.active(settings, cryptoCode)) return
|
||||
console.log('DEBUG334')
|
||||
|
||||
logger.debug('[%s] Pushing trade: %d', market, cryptoAtoms)
|
||||
if (!tradesQueues[market]) tradesQueues[market] = []
|
||||
|
|
@ -485,7 +484,6 @@ function plugins (settings, deviceId) {
|
|||
function sweepHdRow (row) {
|
||||
const cryptoCode = row.crypto_code
|
||||
|
||||
console.log('DEBUG200')
|
||||
return wallet.sweep(settings, cryptoCode, row.hd_index)
|
||||
.then(txHash => {
|
||||
if (txHash) {
|
||||
|
|
|
|||
|
|
@ -17,11 +17,9 @@ function sendMessage (account, rec) {
|
|||
from: account.fromNumber
|
||||
}
|
||||
|
||||
console.log('DEBUG111: %j', opts)
|
||||
|
||||
return client.sendMessage(opts)
|
||||
.catch(err => {
|
||||
console.log('DEBUG113: %s', err)
|
||||
if (_.includes(err.code, BAD_NUMBER_CODES)) {
|
||||
const badNumberError = new Error(err.message)
|
||||
badNumberError.name = 'BadNumberError'
|
||||
|
|
@ -30,7 +28,6 @@ function sendMessage (account, rec) {
|
|||
|
||||
throw new Error(err.message)
|
||||
})
|
||||
.then(_.tap(() => console.log('DEBUG112')))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
|||
|
|
@ -90,7 +90,6 @@ function getTx (req, res, next) {
|
|||
|
||||
function getPhoneTx (req, res, next) {
|
||||
if (req.query.phone) {
|
||||
console.log('DEBUG120: %s', req.query.phone)
|
||||
return helpers.fetchPhoneTx(req.query.phone)
|
||||
.then(r => res.json(r))
|
||||
.catch(next)
|
||||
|
|
@ -322,7 +321,6 @@ let oldVersionId = 'initial'
|
|||
function populateSettings (req, res, next) {
|
||||
const versionId = req.headers['config-version']
|
||||
if (versionId !== oldVersionId) {
|
||||
console.log('DEBUG611: %s', versionId)
|
||||
oldVersionId = versionId
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,11 +6,7 @@ const argv = require('minimist')(process.argv.slice(2))
|
|||
const pify = require('pify')
|
||||
|
||||
const db = require('./db')
|
||||
const options = require('./options')
|
||||
const logger = require('./logger')
|
||||
|
||||
const schemaPath = path.resolve(options.lamassuServerPath, 'lamassu-schema.json')
|
||||
const schema = require(schemaPath)
|
||||
const configValidate = require('./config-validate')
|
||||
|
||||
let settingsCache
|
||||
|
||||
|
|
@ -69,17 +65,25 @@ function loadConfig (versionId) {
|
|||
|
||||
const sql = `select data
|
||||
from user_config
|
||||
where id=$1 and type=$2`
|
||||
where id=$1 and type=$2
|
||||
and valid`
|
||||
|
||||
return db.oneOrNone(sql, [versionId, 'config'])
|
||||
.then(row => row ? row.data.config : [])
|
||||
.then(validate)
|
||||
return db.one(sql, [versionId, 'config'])
|
||||
.then(row => row.data.config)
|
||||
.then(configValidate.validate)
|
||||
.catch(err => {
|
||||
if (err.name === 'QueryResultError') {
|
||||
throw new Error('No such config version: ' + versionId)
|
||||
}
|
||||
|
||||
throw err
|
||||
})
|
||||
}
|
||||
|
||||
function loadLatestConfig () {
|
||||
if (argv.fixture) return loadFixture()
|
||||
|
||||
const sql = `select data
|
||||
const sql = `select id, valid, data
|
||||
from user_config
|
||||
where type=$1
|
||||
and valid
|
||||
|
|
@ -88,7 +92,7 @@ function loadLatestConfig () {
|
|||
|
||||
return db.one(sql, ['config'])
|
||||
.then(row => row.data.config)
|
||||
.then(validate)
|
||||
.then(configValidate.validate)
|
||||
.catch(err => {
|
||||
if (err.name === 'QueryResultError') {
|
||||
throw new Error('lamassu-server is not configured')
|
||||
|
|
@ -98,38 +102,6 @@ function loadLatestConfig () {
|
|||
})
|
||||
}
|
||||
|
||||
function checkConstraint (entry, constraint) {
|
||||
switch (constraint.code) {
|
||||
case 'min':
|
||||
return entry.fieldValue.value >= constraint.min
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
function validateConstraint (entry, constraint) {
|
||||
const isValid = checkConstraint(entry, constraint)
|
||||
if (!isValid) logger.error(`Validation error: ${entry.fieldLocator.code} [${constraint.code}]`)
|
||||
return isValid
|
||||
}
|
||||
|
||||
function validateEntry (entry) {
|
||||
const fieldCode = entry.fieldLocator.code
|
||||
const schemaEntry = _.find(_.matchesProperty('code', fieldCode), schema.fields)
|
||||
if (!schemaEntry) throw new Error(`Unsupported field: ${fieldCode}`)
|
||||
|
||||
const validations = schemaEntry.fieldValidation
|
||||
return _.every(constraint => validateConstraint(entry, constraint), validations)
|
||||
}
|
||||
|
||||
function isValid (config) {
|
||||
return _.every(validateEntry, config)
|
||||
}
|
||||
function validate (config) {
|
||||
if (!isValid(config)) throw new Error('Invalid config')
|
||||
return config
|
||||
}
|
||||
|
||||
function loadAccounts () {
|
||||
const toFields = fieldArr => _.fromPairs(_.map(r => [r.code, r.value], fieldArr))
|
||||
const toPairs = r => [r.code, toFields(r.fields)]
|
||||
|
|
@ -147,7 +119,10 @@ function settings () {
|
|||
|
||||
function save (config) {
|
||||
const sql = 'insert into user_config (type, data, valid) values ($1, $2, $3)'
|
||||
return db.none(sql, ['config', {config}, isValid(config)])
|
||||
|
||||
return configValidate.validate(config)
|
||||
.then(() => db.none(sql, ['config', {config}, true]))
|
||||
.catch(() => db.none(sql, ['config', {config}, false]))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
const util = require('util')
|
||||
const config = require('./admin/config')
|
||||
|
||||
function valid () {
|
||||
return config.validateCurrentConfig()
|
||||
.then(errors => {
|
||||
if (errors.length === 0) return
|
||||
throw new Error('Schema validation error: ' + util.inspect(errors, {colors: true}))
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {valid}
|
||||
|
|
@ -30,7 +30,6 @@ function fetchWallet (settings, cryptoCode) {
|
|||
.then(hex => {
|
||||
const masterSeed = Buffer.from(hex.trim(), 'hex')
|
||||
const plugin = configManager.cryptoScoped(cryptoCode, settings.config).wallet
|
||||
console.log('DEBUG555: %s', plugin)
|
||||
const wallet = ph.load(ph.WALLET, plugin)
|
||||
const account = settings.accounts[plugin]
|
||||
|
||||
|
|
|
|||
|
|
@ -32713,7 +32713,7 @@ var _user$project$TransactionTypes$CashOutTxRec = function (a) {
|
|||
return function (m) {
|
||||
return function (n) {
|
||||
return function (o) {
|
||||
return {id: a, machineName: b, toAddress: c, cryptoAtoms: d, cryptoCode: e, fiat: f, fiatCode: g, status: h, dispensed: i, notified: j, redeemed: k, phone: l, error: m, created: n, confirmed: o};
|
||||
return {id: a, machineName: b, toAddress: c, cryptoAtoms: d, cryptoCode: e, fiat: f, fiatCode: g, status: h, dispense: i, notified: j, redeemed: k, phone: l, error: m, created: n, confirmed: o};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -32833,7 +32833,7 @@ var _user$project$TransactionDecoder$cashOutTxDecoder = A3(
|
|||
_elm_lang$core$Json_Decode$bool,
|
||||
A3(
|
||||
_NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required,
|
||||
'dispensed',
|
||||
'dispense',
|
||||
_elm_lang$core$Json_Decode$bool,
|
||||
A3(
|
||||
_NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue