diff --git a/lamassu-admin-elm/src/Transactions.elm b/lamassu-admin-elm/src/Transactions.elm index d4870f21..9b9f6134 100644 --- a/lamassu-admin-elm/src/Transactions.elm +++ b/lamassu-admin-elm/src/Transactions.elm @@ -111,10 +111,10 @@ rowView tx = [ C.CashIn ] status = - if isJust cashIn.error then - "Error" - else if cashIn.operatorCompleted then + if cashIn.operatorCompleted then "Cancelled" + else if isJust cashIn.error then + "Error" else if cashIn.sendConfirmed then "Sent" else if cashIn.expired then diff --git a/lib/blacklist.js b/lib/blacklist.js new file mode 100644 index 00000000..5c9c89ba --- /dev/null +++ b/lib/blacklist.js @@ -0,0 +1,11 @@ +const db = require('./db') + +function blocked (address, cryptoCode) { + const sql = `select * from blacklist where address = $1 and crypto_code = $2` + return db.oneOrNone(sql, [ + address, + cryptoCode + ]) +} + +module.exports = { blocked } diff --git a/lib/cash-in/cash-in-low.js b/lib/cash-in/cash-in-low.js index 3348e62b..0e000c22 100644 --- a/lib/cash-in/cash-in-low.js +++ b/lib/cash-in/cash-in-low.js @@ -8,7 +8,7 @@ const E = require('../error') const PENDING_INTERVAL_MS = 60 * T.minutes -const massage = _.flow(_.omit(['direction', 'cryptoNetwork', 'bills']), +const massage = _.flow(_.omit(['direction', 'cryptoNetwork', 'bills', 'blacklisted']), convertBigNumFields, _.mapKeys(_.snakeCase)) module.exports = {toObj, upsert, insert, update, massage, isClearToSend} diff --git a/lib/cash-in/cash-in-tx.js b/lib/cash-in/cash-in-tx.js index 889f5af9..16017c24 100644 --- a/lib/cash-in/cash-in-tx.js +++ b/lib/cash-in/cash-in-tx.js @@ -2,6 +2,7 @@ const _ = require('lodash/fp') const pgp = require('pg-promise')() const pEachSeries = require('p-each-series') +const blacklist = require('../blacklist') const db = require('../db') const plugins = require('../plugins') const logger = require('../logger') @@ -18,10 +19,16 @@ function post (machineTx, pi) { return db.tx(cashInAtomic.atomic(machineTx, pi)) .then(r => { const updatedTx = r.tx + let blacklisted = false - return postProcess(r, pi) + return checkForBlacklisted(updatedTx) + .then(isBlacklisted => { + blacklisted = !!isBlacklisted + return postProcess(r, pi, blacklisted) + }) .then(changes => cashInLow.update(db, updatedTx, changes)) .then(tx => _.set('bills', machineTx.bills, tx)) + .then(tx => _.set('blacklisted', blacklisted, tx)) }) } @@ -51,7 +58,22 @@ function logActionById (action, _rec, txId) { return db.none(sql) } -function postProcess (r, pi) { +function checkForBlacklisted (tx) { + // Check only on addressScan and avoid testing for blacklist on every bill inserted + if (!tx.fiat || tx.fiat.isZero()) { + return blacklist.blocked(tx.toAddress, tx.cryptoCode) + } + return Promise.resolve(false) +} + +function postProcess (r, pi, isBlacklisted) { + if (isBlacklisted) { + return Promise.resolve({ + operatorCompleted: true, + error: 'Blacklisted Address' + }) + } + registerTrades(pi, r.newBills) if (!cashInLow.isClearToSend(r.dbTx, r.tx)) return Promise.resolve({}) diff --git a/migrations/1556582597515-blacklist.js b/migrations/1556582597515-blacklist.js new file mode 100644 index 00000000..0436a2f4 --- /dev/null +++ b/migrations/1556582597515-blacklist.js @@ -0,0 +1,17 @@ +var db = require('./db') + +exports.up = function (next) { + const sql = + [`create table blacklist ( + crypto_code text not null, + address text not null, + unique (crypto_code, address) + )` + ] + + db.multi(sql, next) +} + +exports.down = function (next) { + next() +} diff --git a/public/elm.js b/public/elm.js index a2b662e2..5591b584 100644 --- a/public/elm.js +++ b/public/elm.js @@ -34172,7 +34172,7 @@ var _user$project$Transactions$rowView = function (tx) { var _p2 = tx; if (_p2.ctor === 'CashInTx') { var _p3 = _p2._0; - var status = _elm_community$maybe_extra$Maybe_Extra$isJust(_p3.error) ? 'Error' : (_p3.operatorCompleted ? 'Cancelled' : (_p3.sendConfirmed ? 'Sent' : (_p3.expired ? 'Expired' : 'Pending'))); + var status = _p3.operatorCompleted ? 'Cancelled' : (_elm_community$maybe_extra$Maybe_Extra$isJust(_p3.error) ? 'Error' : (_p3.sendConfirmed ? 'Sent' : (_p3.expired ? 'Expired' : 'Pending'))); var rowClasses = _p3.operatorCompleted ? { ctor: '::', _0: _user$project$Css_Classes$CashIn,