Log unsuccessful trade attempts in the db (#224)

* Save trade error in table trades

* Add one migration, Add error column to trades table

* changes in plugins.js file

* Apply standardjs to plugins.js file
This commit is contained in:
Davit Abulashvili 2018-11-28 22:24:48 +04:00 committed by Josh Harvey
parent 13040f41a1
commit 907cd08cf1
3 changed files with 103 additions and 41 deletions

View file

@ -21,7 +21,9 @@ const machineLoader = require('./machine-loader')
const customers = require('./customers') const customers = require('./customers')
const coinUtils = require('./coin-utils') const coinUtils = require('./coin-utils')
const mapValuesWithKey = _.mapValues.convert({cap: false}) const mapValuesWithKey = _.mapValues.convert({
cap: false
})
const TRADE_TTL = 2 * T.minutes const TRADE_TTL = 2 * T.minutes
const STALE_TICKER = 3 * T.minutes const STALE_TICKER = 3 * T.minutes
@ -132,8 +134,9 @@ function plugins (settings, deviceId) {
if (!config.cashOutEnabled) return Promise.resolve() if (!config.cashOutEnabled) return Promise.resolve()
const denominations = [ config.topCashOutDenomination, const denominations = [config.topCashOutDenomination,
config.bottomCashOutDenomination ] config.bottomCashOutDenomination
]
const virtualCassettes = [config.virtualCashOutDenomination] const virtualCassettes = [config.virtualCashOutDenomination]
return Promise.all([dbm.cassetteCounts(deviceId), cashOutHelper.redeemableTxs(deviceId, excludeTxId)]) return Promise.all([dbm.cassetteCounts(deviceId), cashOutHelper.redeemableTxs(deviceId, excludeTxId)])
@ -162,17 +165,20 @@ function plugins (settings, deviceId) {
} }
} catch (err) { } catch (err) {
logger.error(err) logger.error(err)
return {cassettes, virtualCassettes} return {
cassettes,
virtualCassettes
}
} }
}) })
} }
function fetchCurrentConfigVersion () { function fetchCurrentConfigVersion () {
const sql = `select id from user_config const sql = `select id from user_config
where type=$1 where type=$1
and valid and valid
order by id desc order by id desc
limit 1` limit 1`
return db.one(sql, ['config']) return db.one(sql, ['config'])
.then(row => row.id) .then(row => row.id)
@ -243,8 +249,10 @@ function plugins (settings, deviceId) {
return Promise.all([ return Promise.all([
db.none(`insert into machine_pings(device_id, device_time) values($1, $2) db.none(`insert into machine_pings(device_id, device_time) values($1, $2)
ON CONFLICT (device_id) DO UPDATE SET device_time = $2`, [deviceId, deviceTime]), ON CONFLICT (device_id) DO UPDATE SET device_time = $2`, [deviceId, deviceTime]),
db.none(pgp.helpers.update(devices, null, 'devices') + 'WHERE device_id = ${deviceId}', { deviceId }) db.none(pgp.helpers.update(devices, null, 'devices') + 'WHERE device_id = ${deviceId}', {
deviceId
})
]) ])
} }
@ -270,8 +278,9 @@ function plugins (settings, deviceId) {
function dispenseAck (tx) { function dispenseAck (tx) {
const config = configManager.machineScoped(deviceId, settings.config) const config = configManager.machineScoped(deviceId, settings.config)
const cassettes = [ config.topCashOutDenomination, const cassettes = [config.topCashOutDenomination,
config.bottomCashOutDenomination ] config.bottomCashOutDenomination
]
return dbm.addDispense(deviceId, tx, cassettes) return dbm.addDispense(deviceId, tx, cassettes)
} }
@ -300,7 +309,10 @@ function plugins (settings, deviceId) {
const shiftedRate = rate.shift(-unitScale) const shiftedRate = rate.shift(-unitScale)
const fiatTransferBalance = balance.mul(shiftedRate).div(lowBalanceMargin) const fiatTransferBalance = balance.mul(shiftedRate).div(lowBalanceMargin)
return {timestamp: balanceRec.timestamp, balance: fiatTransferBalance.truncated().toString()} return {
timestamp: balanceRec.timestamp,
balance: fiatTransferBalance.truncated().toString()
}
}) })
} }
@ -355,15 +367,15 @@ function plugins (settings, deviceId) {
} }
const body = ` const body = `
- Transaction ID: ${tx.id} - Transaction ID: ${tx.id}
- Status: ${status} - Status: ${status}
- Machine name: ${machineName} - Machine name: ${machineName}
- ${direction} - ${direction}
- ${fiat} - ${fiat}
- ${crypto} - ${crypto}
- Customer: ${customerName} - Customer: ${customerName}
${phone} ${phone}
` `
const subject = `A transaction just happened` const subject = `A transaction just happened`
return { return {
@ -387,7 +399,10 @@ function plugins (settings, deviceId) {
sms: { sms: {
body: `${subject} - ${body}` body: `${subject} - ${body}`
}, },
email: { subject, body } email: {
subject,
body
}
} }
return sendTransactionMessage(rec) return sendTransactionMessage(rec)
} }
@ -399,16 +414,16 @@ function plugins (settings, deviceId) {
function pongClear () { function pongClear () {
const sql = `delete from server_events const sql = `delete from server_events
where event_type=$1 where event_type=$1
and created < now() - interval $2` and created < now() - interval $2`
db.none(sql, ['ping', PONG_TTL]) db.none(sql, ['ping', PONG_TTL])
.catch(logger.error) .catch(logger.error)
} }
/* /*
* Trader functions * Trader functions
*/ */
function buy (rec) { function buy (rec) {
return buyAndSell(rec, true) return buyAndSell(rec, true)
@ -489,7 +504,10 @@ function plugins (settings, deviceId) {
const fiatCode = config.fiatCurrency const fiatCode = config.fiatCurrency
const cryptoCodes = config.cryptoCurrencies const cryptoCodes = config.cryptoCurrencies
return cryptoCodes.map(cryptoCode => ({fiatCode, cryptoCode})) return cryptoCodes.map(cryptoCode => ({
fiatCode,
cryptoCode
}))
}) })
const tradesPromises = _.uniq(_.flatten(lists)) const tradesPromises = _.uniq(_.flatten(lists))
@ -527,6 +545,12 @@ function plugins (settings, deviceId) {
return execute(settings, tradeEntry.cryptoAtoms, tradeEntry.fiatCode, tradeEntry.cryptoCode) return execute(settings, tradeEntry.cryptoAtoms, tradeEntry.fiatCode, tradeEntry.cryptoCode)
.then(() => recordTrade(tradeEntry)) .then(() => recordTrade(tradeEntry))
.catch(err => {
return recordTrade(tradeEntry, err)
.then(() => {
throw err
})
})
} }
function convertBigNumFields (obj) { function convertBigNumFields (obj) {
@ -541,14 +565,23 @@ function plugins (settings, deviceId) {
return _.mapKeys(convertKey, mapValuesWithKey(convert, obj)) return _.mapKeys(convertKey, mapValuesWithKey(convert, obj))
} }
function recordTrade (_tradeEntry) { function mergeTradeEntryAndError (tradeEntry, error) {
if (error && error.message) {
return Object.assign({}, tradeEntry, {
error: error.message.slice(0, 200)
})
}
return tradeEntry
}
function recordTrade (_tradeEntry, error) {
const massage = _.flow( const massage = _.flow(
_.pick(['cryptoCode', 'cryptoAtoms', 'fiatCode', 'type']), mergeTradeEntryAndError,
_.pick(['cryptoCode', 'cryptoAtoms', 'fiatCode', 'type', 'error']),
convertBigNumFields, convertBigNumFields,
_.mapKeys(_.snakeCase) _.mapKeys(_.snakeCase)
) )
const tradeEntry = massage(_tradeEntry, error)
const tradeEntry = massage(_tradeEntry)
const sql = pgp.helpers.insert(tradeEntry, null, 'trades') const sql = pgp.helpers.insert(tradeEntry, null, 'trades')
return db.none(sql) return db.none(sql)
} }
@ -585,27 +618,36 @@ function plugins (settings, deviceId) {
const cashOutEnabled = config.cashOutEnabled const cashOutEnabled = config.cashOutEnabled
const cashInAlert = device.cashbox > config.cashInAlertThreshold const cashInAlert = device.cashbox > config.cashInAlertThreshold
? {code: 'CASH_BOX_FULL', machineName, deviceId: device.deviceId, notes: device.cashbox} ? {
code: 'CASH_BOX_FULL',
machineName,
deviceId: device.deviceId,
notes: device.cashbox
}
: null : null
const cassette1Alert = cashOutEnabled && device.cassette1 < config.cashOutCassette1AlertThreshold const cassette1Alert = cashOutEnabled && device.cassette1 < config.cashOutCassette1AlertThreshold
? {code: 'LOW_CASH_OUT', ? {
code: 'LOW_CASH_OUT',
cassette: 1, cassette: 1,
machineName, machineName,
deviceId: device.deviceId, deviceId: device.deviceId,
notes: device.cassette1, notes: device.cassette1,
denomination: denomination1, denomination: denomination1,
fiatCode} fiatCode
}
: null : null
const cassette2Alert = cashOutEnabled && device.cassette2 < config.cashOutCassette2AlertThreshold const cassette2Alert = cashOutEnabled && device.cassette2 < config.cashOutCassette2AlertThreshold
? {code: 'LOW_CASH_OUT', ? {
code: 'LOW_CASH_OUT',
cassette: 2, cassette: 2,
machineName, machineName,
deviceId: device.deviceId, deviceId: device.deviceId,
notes: device.cassette2, notes: device.cassette2,
denomination: denomination2, denomination: denomination2,
fiatCode} fiatCode
}
: null : null
return _.compact([cashInAlert, cassette1Alert, cassette2Alert]) return _.compact([cashInAlert, cassette1Alert, cassette2Alert])
@ -636,7 +678,12 @@ function plugins (settings, deviceId) {
const cryptoAlertThreshold = config.cryptoAlertThreshold const cryptoAlertThreshold = config.cryptoAlertThreshold
return BN(fiatBalance.balance).lt(cryptoAlertThreshold) return BN(fiatBalance.balance).lt(cryptoAlertThreshold)
? {code: 'LOW_CRYPTO_BALANCE', cryptoCode, fiatBalance, fiatCode} ? {
code: 'LOW_CRYPTO_BALANCE',
cryptoCode,
fiatBalance,
fiatCode
}
: null : null
} }
@ -683,7 +730,7 @@ function plugins (settings, deviceId) {
logger.debug('[%s] Swept address with tx: %s', cryptoCode, txHash) logger.debug('[%s] Swept address with tx: %s', cryptoCode, txHash)
const sql = `update cash_out_txs set swept='t' const sql = `update cash_out_txs set swept='t'
where id=$1` where id=$1`
return db.none(sql, row.id) return db.none(sql, row.id)
} }
@ -693,7 +740,7 @@ function plugins (settings, deviceId) {
function sweepHd () { function sweepHd () {
const sql = `select id, crypto_code, hd_index from cash_out_txs const sql = `select id, crypto_code, hd_index from cash_out_txs
where hd_index is not null and not swept and status in ('confirmed', 'instant')` where hd_index is not null and not swept and status in ('confirmed', 'instant')`
return db.any(sql) return db.any(sql)
.then(rows => Promise.all(rows.map(sweepHdRow))) .then(rows => Promise.all(rows.map(sweepHdRow)))

View file

@ -0,0 +1,15 @@
var db = require('./db')
exports.up = function (next) {
const sql = [
'alter table trades add column error text',
]
db.multi(sql, next)
}
exports.down = function (next) {
const sql = ['alter table trades drop column error']
db.multi(sql, next)
}

2
package-lock.json generated
View file

@ -3281,7 +3281,7 @@
"dependencies": { "dependencies": {
"doctrine": { "doctrine": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "http://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
"integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
"dev": true, "dev": true,
"requires": { "requires": {