From 473bb15c24f4250937959d8287a2a199150f4159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Salgado?= Date: Tue, 4 Oct 2022 19:28:18 +0100 Subject: [PATCH 01/14] feat: turn address into a coin-agnostic solution --- lib/blacklist.js | 29 ++- lib/cash-in/cash-in-tx.js | 2 +- .../graphql/resolvers/blacklist.resolver.js | 8 +- lib/new-admin/graphql/types/blacklist.type.js | 5 +- .../1664907000312-coin-agnostic-blacklist.js | 18 ++ .../src/pages/Blacklist/Blacklist.js | 175 +++++++----------- .../src/pages/Blacklist/Blacklist.styles.js | 10 +- .../src/pages/Blacklist/BlacklistModal.js | 39 +--- .../src/pages/Blacklist/BlacklistTable.js | 13 +- 9 files changed, 122 insertions(+), 177 deletions(-) create mode 100644 migrations/1664907000312-coin-agnostic-blacklist.js diff --git a/lib/blacklist.js b/lib/blacklist.js index 4c3d8595..15bd7b12 100644 --- a/lib/blacklist.js +++ b/lib/blacklist.js @@ -5,38 +5,37 @@ const notifierQueries = require('./notifier/queries') const getBlacklist = () => { return db.any(`SELECT * FROM blacklist`).then(res => res.map(item => ({ - cryptoCode: item.crypto_code, address: item.address })) ) } // Delete row from blacklist table by crypto code and address -const deleteFromBlacklist = (cryptoCode, address) => { - const sql = `DELETE FROM blacklist WHERE crypto_code = $1 AND address = $2` - notifierQueries.clearBlacklistNotification(cryptoCode, address) - return db.none(sql, [cryptoCode, address]) +const deleteFromBlacklist = address => { + const sql = `DELETE FROM blacklist WHERE address = $1` + notifierQueries.clearBlacklistNotification(address) + return db.none(sql, [address]) } -const insertIntoBlacklist = (cryptoCode, address) => { +const insertIntoBlacklist = address => { return db .none( - 'INSERT INTO blacklist (crypto_code, address) VALUES ($1, $2);', - [cryptoCode, address] + 'INSERT INTO blacklist (address) VALUES ($1);', + [address] ) } -function blocked (address, cryptoCode) { - const sql = `SELECT * FROM blacklist WHERE address = $1 AND crypto_code = $2` - return db.any(sql, [address, cryptoCode]) +function blocked (address) { + const sql = `SELECT * FROM blacklist WHERE address = $1` + return db.any(sql, [address]) } -function addToUsedAddresses (address, cryptoCode) { +function addToUsedAddresses (address) { // ETH reuses addresses - if (cryptoCode === 'ETH') return Promise.resolve() + // if (cryptoCode === 'ETH') return Promise.resolve() - const sql = `INSERT INTO blacklist (crypto_code, address) VALUES ($1, $2)` - return db.oneOrNone(sql, [cryptoCode, address]) + const sql = `INSERT INTO blacklist (address) VALUES ($1)` + return db.oneOrNone(sql, [address]) } module.exports = { diff --git a/lib/cash-in/cash-in-tx.js b/lib/cash-in/cash-in-tx.js index cc676554..5123eeb6 100644 --- a/lib/cash-in/cash-in-tx.js +++ b/lib/cash-in/cash-in-tx.js @@ -94,7 +94,7 @@ function logActionById (action, _rec, txId) { } function checkForBlacklisted (tx) { - return blacklist.blocked(tx.toAddress, tx.cryptoCode) + return blacklist.blocked(tx.toAddress) } function postProcess (r, pi, isBlacklisted, addressReuse, walletScore) { diff --git a/lib/new-admin/graphql/resolvers/blacklist.resolver.js b/lib/new-admin/graphql/resolvers/blacklist.resolver.js index 8c15e43f..7cb825cc 100644 --- a/lib/new-admin/graphql/resolvers/blacklist.resolver.js +++ b/lib/new-admin/graphql/resolvers/blacklist.resolver.js @@ -5,10 +5,10 @@ const resolvers = { blacklist: () => blacklist.getBlacklist() }, Mutation: { - deleteBlacklistRow: (...[, { cryptoCode, address }]) => - blacklist.deleteFromBlacklist(cryptoCode, address), - insertBlacklistRow: (...[, { cryptoCode, address }]) => - blacklist.insertIntoBlacklist(cryptoCode, address) + deleteBlacklistRow: (...[, { address }]) => + blacklist.deleteFromBlacklist(address), + insertBlacklistRow: (...[, { address }]) => + blacklist.insertIntoBlacklist(address) } } diff --git a/lib/new-admin/graphql/types/blacklist.type.js b/lib/new-admin/graphql/types/blacklist.type.js index 3cd1bfa1..ee9ee149 100644 --- a/lib/new-admin/graphql/types/blacklist.type.js +++ b/lib/new-admin/graphql/types/blacklist.type.js @@ -2,7 +2,6 @@ const { gql } = require('apollo-server-express') const typeDef = gql` type Blacklist { - cryptoCode: String! address: String! } @@ -11,8 +10,8 @@ const typeDef = gql` } type Mutation { - deleteBlacklistRow(cryptoCode: String!, address: String!): Blacklist @auth - insertBlacklistRow(cryptoCode: String!, address: String!): Blacklist @auth + deleteBlacklistRow(address: String!): Blacklist @auth + insertBlacklistRow(address: String!): Blacklist @auth } ` diff --git a/migrations/1664907000312-coin-agnostic-blacklist.js b/migrations/1664907000312-coin-agnostic-blacklist.js new file mode 100644 index 00000000..9cd78a5f --- /dev/null +++ b/migrations/1664907000312-coin-agnostic-blacklist.js @@ -0,0 +1,18 @@ +var db = require('./db') + +exports.up = function (next) { + var sql = [ + `CREATE TABLE blacklist_temp ( + address TEXT NOT NULL UNIQUE + )` + `INSERT INTO blacklist_temp (address) SELECT DISTINCT address FROM blacklist`, + `DROP TABLE blacklist`, + `ALTER TABLE blacklist_temp RENAME TO blacklist` + ] + + db.multi(sql, next) +} + +exports.down = function (next) { + next() +} diff --git a/new-lamassu-admin/src/pages/Blacklist/Blacklist.js b/new-lamassu-admin/src/pages/Blacklist/Blacklist.js index dec75592..7726ddba 100644 --- a/new-lamassu-admin/src/pages/Blacklist/Blacklist.js +++ b/new-lamassu-admin/src/pages/Blacklist/Blacklist.js @@ -1,5 +1,5 @@ import { useQuery, useMutation } from '@apollo/react-hooks' -import { utils as coinUtils } from '@lamassu/coins' +import { addressDetector } from '@lamassu/coins' import { Box, Dialog, DialogContent, DialogActions } from '@material-ui/core' import Grid from '@material-ui/core/Grid' import { makeStyles } from '@material-ui/core/styles' @@ -8,16 +8,10 @@ import * as R from 'ramda' import React, { useState } from 'react' import { HelpTooltip } from 'src/components/Tooltip' -import { - Link, - Button, - IconButton, - SupportLinkButton -} from 'src/components/buttons' +import { Link, Button, IconButton } from 'src/components/buttons' import { Switch } from 'src/components/inputs' -import Sidebar from 'src/components/layout/Sidebar' import TitleSection from 'src/components/layout/TitleSection' -import { H4, H2, Label2, P, Info3, Info2 } from 'src/components/typography' +import { H2, Label2, P, Info3, Info2 } from 'src/components/typography' import { ReactComponent as CloseIcon } from 'src/styling/icons/action/close/zodiac.svg' import { fromNamespace, toNamespace } from 'src/utils/config' @@ -27,12 +21,9 @@ import BlacklistTable from './BlacklistTable' const useStyles = makeStyles(styles) -const groupByCode = R.groupBy(obj => obj.cryptoCode) - const DELETE_ROW = gql` - mutation DeleteBlacklistRow($cryptoCode: String!, $address: String!) { - deleteBlacklistRow(cryptoCode: $cryptoCode, address: $address) { - cryptoCode + mutation DeleteBlacklistRow($address: String!) { + deleteBlacklistRow(address: $address) { address } } @@ -41,7 +32,6 @@ const DELETE_ROW = gql` const GET_BLACKLIST = gql` query getBlacklistData { blacklist { - cryptoCode address } cryptoCurrencies { @@ -64,9 +54,8 @@ const GET_INFO = gql` ` const ADD_ROW = gql` - mutation InsertBlacklistRow($cryptoCode: String!, $address: String!) { - insertBlacklistRow(cryptoCode: $cryptoCode, address: $address) { - cryptoCode + mutation InsertBlacklistRow($address: String!) { + insertBlacklistRow(address: $address) { address } } @@ -118,10 +107,6 @@ const Blacklist = () => { const { data: blacklistResponse } = useQuery(GET_BLACKLIST) const { data: configData } = useQuery(GET_INFO) const [showModal, setShowModal] = useState(false) - const [clickedItem, setClickedItem] = useState({ - code: 'BTC', - display: 'Bitcoin' - }) const [errorMsg, setErrorMsg] = useState(null) const [deleteDialog, setDeleteDialog] = useState(false) const [confirmDialog, setConfirmDialog] = useState(false) @@ -147,11 +132,6 @@ const Blacklist = () => { const classes = useStyles() const blacklistData = R.path(['blacklist'])(blacklistResponse) ?? [] - const availableCurrencies = R.filter( - coin => coinUtils.getEquivalentCode(coin.code) === coin.code - )(R.path(['cryptoCurrencies'], blacklistResponse) ?? []) - - const formattedData = groupByCode(blacklistData) const complianceConfig = configData?.config && fromNamespace('compliance')(configData.config) @@ -165,12 +145,8 @@ const Blacklist = () => { return saveConfig({ variables: { config } }) } - const onClickSidebarItem = e => { - setClickedItem({ code: e.code, display: e.display }) - } - - const handleDeleteEntry = (cryptoCode, address) => { - deleteEntry({ variables: { cryptoCode, address } }) + const handleDeleteEntry = address => { + deleteEntry({ variables: { address } }) } const handleConfirmDialog = confirm => { @@ -180,21 +156,21 @@ const Blacklist = () => { setConfirmDialog(false) } - const validateAddress = (cryptoCode, address) => { + const validateAddress = address => { try { - return !R.isNil(coinUtils.parseUrl(cryptoCode, 'main', address)) + return !R.isEmpty(addressDetector.detectAddress(address).matches) } catch { return false } } - const addToBlacklist = async (cryptoCode, address) => { + const addToBlacklist = async address => { setErrorMsg(null) - if (!validateAddress(cryptoCode, address)) { + if (!validateAddress(address)) { setErrorMsg('Invalid address') return } - const res = await addEntry({ variables: { cryptoCode, address } }) + const res = await addEntry({ variables: { address } }) if (!res.errors) { return setShowModal(false) } @@ -218,86 +194,64 @@ const Blacklist = () => { }} /> - + + +

Enable paper wallet (only)

+ + enablePaperWalletOnly + ? addressReuseSave({ + enablePaperWalletOnly: e.target.checked + }) + : setConfirmDialog(true) + } + value={enablePaperWalletOnly} + /> + {enablePaperWalletOnly ? 'On' : 'Off'} + +

+ The "Enable paper wallet (only)" option means that only paper + wallets will be printed for users, and they won't be permitted + to scan an address from their own wallet. +

+
+
+ +

Reject reused addresses

+ { + addressReuseSave({ rejectAddressReuse: event.target.checked }) + }} + value={rejectAddressReuse} + /> + {rejectAddressReuse ? 'On' : 'Off'} + +

+ The "Reject reused addresses" option means that all addresses + that are used once will be automatically rejected if there's an + attempt to use them again on a new transaction. +

+
+
setShowModal(true)}> Blacklist new addresses
- it.display} - onClick={onClickSidebarItem} - />
- -

- {clickedItem.display - ? `${clickedItem.display} blacklisted addresses` - : ''}{' '} -

- -

Enable paper wallet (only)

- - enablePaperWalletOnly - ? addressReuseSave({ - enablePaperWalletOnly: e.target.checked - }) - : setConfirmDialog(true) - } - value={enablePaperWalletOnly} - /> - {enablePaperWalletOnly ? 'On' : 'Off'} - -

- The "Enable paper wallet (only)" option means that only paper - wallets will be printed for users, and they won't be permitted - to scan an address from their own wallet. -

-
-
- -

Reject reused addresses

- { - addressReuseSave({ rejectAddressReuse: event.target.checked }) - }} - value={rejectAddressReuse} - /> - {rejectAddressReuse ? 'On' : 'Off'} - -

- The "Reject reused addresses" option means that all addresses - that are used once will be automatically rejected if there's - an attempt to use them again on a new transaction. -

-

- For details please read the relevant knowledgebase article: -

- -
-
-
{ setShowModal(false) }} errorMsg={errorMsg} - selectedCoin={clickedItem} addToBlacklist={addToBlacklist} /> )} diff --git a/new-lamassu-admin/src/pages/Blacklist/Blacklist.styles.js b/new-lamassu-admin/src/pages/Blacklist/Blacklist.styles.js index 9c44bb1d..6e4a09e4 100644 --- a/new-lamassu-admin/src/pages/Blacklist/Blacklist.styles.js +++ b/new-lamassu-admin/src/pages/Blacklist/Blacklist.styles.js @@ -7,11 +7,15 @@ const styles = { content: { display: 'flex', flexDirection: 'column', - flex: 1, - marginLeft: spacer * 6 + flex: 1 }, footer: { - margin: [['auto', 0, spacer * 3, 'auto']] + display: 'flex', + flexDirection: 'row', + margin: [['auto', 0, spacer * 3, 0]] + }, + submit: { + margin: [['auto', 0, 0, 'auto']] }, modalTitle: { margin: [['auto', 0, 8.5, 'auto']] diff --git a/new-lamassu-admin/src/pages/Blacklist/BlacklistModal.js b/new-lamassu-admin/src/pages/Blacklist/BlacklistModal.js index 4c13881b..5e9eb95a 100644 --- a/new-lamassu-admin/src/pages/Blacklist/BlacklistModal.js +++ b/new-lamassu-admin/src/pages/Blacklist/BlacklistModal.js @@ -14,31 +14,14 @@ import { H3 } from 'src/components/typography' import styles from './Blacklist.styles' const useStyles = makeStyles(styles) -const BlackListModal = ({ - onClose, - selectedCoin, - addToBlacklist, - errorMsg -}) => { +const BlackListModal = ({ onClose, addToBlacklist, errorMsg }) => { const classes = useStyles() const handleAddToBlacklist = address => { - if (selectedCoin.code === 'BCH' && !address.startsWith('bitcoincash:')) { - address = 'bitcoincash:' + address - } - addToBlacklist(selectedCoin.code, address) - } - const placeholderAddress = { - BTC: '1ADwinnimZKGgQ3dpyfoUZvJh4p1UWSSpD', - ETH: '0x71C7656EC7ab88b098defB751B7401B5f6d8976F', - LTC: 'LPKvbjwV1Kaksktzkr7TMK3FQtQEEe6Wqa', - DASH: 'XqQ7gU8eM76rEfey726cJpT2RGKyJyBrcn', - ZEC: 't1KGyyv24eL354C9gjveBGEe8Xz9UoPKvHR', - BCH: 'qrd6za97wm03lfyg82w0c9vqgc727rhemg5yd9k3dm', - USDT: '0x5754284f345afc66a98fbb0a0afe71e0f007b949', - XMR: - '888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H' + addToBlacklist(address) } + const placeholderAddress = '1ADwinnimZKGgQ3dpyfoUZvJh4p1UWSSpD' + return (
-

- {selectedCoin.display - ? `Blacklist ${R.toLower(selectedCoin.display)} address` - : ''} -

+

Blacklist new address

- {!R.isNil(errorMsg) && ( - {errorMsg} - )}
- + {!R.isNil(errorMsg) && {errorMsg}} + Blacklist address diff --git a/new-lamassu-admin/src/pages/Blacklist/BlacklistTable.js b/new-lamassu-admin/src/pages/Blacklist/BlacklistTable.js index 9ce480a3..39bcb1ab 100644 --- a/new-lamassu-admin/src/pages/Blacklist/BlacklistTable.js +++ b/new-lamassu-admin/src/pages/Blacklist/BlacklistTable.js @@ -5,7 +5,6 @@ import React, { useState } from 'react' import { DeleteDialog } from 'src/components/DeleteDialog' import { IconButton } from 'src/components/buttons' import DataTable from 'src/components/tables/DataTable' -import { Label1 } from 'src/components/typography' import CopyToClipboard from 'src/pages/Transactions/CopyToClipboard' import { ReactComponent as DeleteIcon } from 'src/styling/icons/action/delete/enabled.svg' @@ -15,7 +14,6 @@ const useStyles = makeStyles(styles) const BlacklistTable = ({ data, - selectedCoin, handleDeleteEntry, errorMessage, setErrorMessage, @@ -29,8 +27,8 @@ const BlacklistTable = ({ const elements = [ { name: 'address', - header: {'Addresses'}, - width: 800, + header: 'Address', + width: 1070, textAlign: 'left', size: 'sm', view: it => ( @@ -41,7 +39,7 @@ const BlacklistTable = ({ }, { name: 'deleteButton', - header: {'Delete'}, + header: 'Delete', width: 130, textAlign: 'center', size: 'sm', @@ -57,14 +55,11 @@ const BlacklistTable = ({ ) } ] - const dataToShow = selectedCoin - ? data[selectedCoin.code] - : data[R.keys(data)[0]] return ( <> Date: Thu, 6 Oct 2022 17:18:12 +0100 Subject: [PATCH 02/14] feat: add advanced address blacklisting --- lib/blacklist.js | 28 ++- .../graphql/resolvers/blacklist.resolver.js | 7 +- lib/new-admin/graphql/types/blacklist.type.js | 10 + .../1664916753772-advanced-blacklisting.js | 26 +++ .../src/pages/Blacklist/Blacklist.js | 174 +++++++++++------ .../src/pages/Blacklist/Blacklist.styles.js | 11 ++ .../src/pages/Blacklist/BlacklistAdvanced.js | 177 ++++++++++++++++++ 7 files changed, 367 insertions(+), 66 deletions(-) create mode 100644 migrations/1664916753772-advanced-blacklisting.js create mode 100644 new-lamassu-admin/src/pages/Blacklist/BlacklistAdvanced.js diff --git a/lib/blacklist.js b/lib/blacklist.js index 15bd7b12..89a9037f 100644 --- a/lib/blacklist.js +++ b/lib/blacklist.js @@ -1,16 +1,16 @@ +const _ = require('lodash/fp') + const db = require('./db') const notifierQueries = require('./notifier/queries') -// Get all blacklist rows from the DB "blacklist" table that were manually inserted by the operator const getBlacklist = () => { - return db.any(`SELECT * FROM blacklist`).then(res => - res.map(item => ({ - address: item.address - })) - ) + const blacklistSql = `SELECT * FROM blacklist` + const messagesSql = `SELECT * FROM blacklist_messages` + return Promise.all([db.any(blacklistSql), db.any(messagesSql)]) + .then(([blacklist, messages]) => Promise.all([_.map(_.mapKeys(_.camelCase), blacklist), _.map(_.mapKeys(_.camelCase), messages)])) + .then(([blacklist, messages]) => _.map(it => ({ ...it, blacklistMessage: _.find(ite => it.blacklistMessageId === ite.id, messages) }), blacklist)) } -// Delete row from blacklist table by crypto code and address const deleteFromBlacklist = address => { const sql = `DELETE FROM blacklist WHERE address = $1` notifierQueries.clearBlacklistNotification(address) @@ -38,10 +38,22 @@ function addToUsedAddresses (address) { return db.oneOrNone(sql, [address]) } +function getMessages () { + const sql = `SELECT * FROM blacklist_messages` + return db.any(sql) +} + +function editBlacklistMessage (id, content) { + const sql = `UPDATE blacklist_messages SET content = $1 WHERE id = $2 RETURNING id` + return db.oneOrNone(sql, [content, id]) +} + module.exports = { blocked, addToUsedAddresses, getBlacklist, deleteFromBlacklist, - insertIntoBlacklist + insertIntoBlacklist, + getMessages, + editBlacklistMessage } diff --git a/lib/new-admin/graphql/resolvers/blacklist.resolver.js b/lib/new-admin/graphql/resolvers/blacklist.resolver.js index 7cb825cc..e0b63d53 100644 --- a/lib/new-admin/graphql/resolvers/blacklist.resolver.js +++ b/lib/new-admin/graphql/resolvers/blacklist.resolver.js @@ -2,13 +2,16 @@ const blacklist = require('../../../blacklist') const resolvers = { Query: { - blacklist: () => blacklist.getBlacklist() + blacklist: () => blacklist.getBlacklist(), + blacklistMessages: () => blacklist.getMessages() }, Mutation: { deleteBlacklistRow: (...[, { address }]) => blacklist.deleteFromBlacklist(address), insertBlacklistRow: (...[, { address }]) => - blacklist.insertIntoBlacklist(address) + blacklist.insertIntoBlacklist(address), + editBlacklistMessage: (...[, { id, content }]) => + blacklist.editBlacklistMessage(id, content) } } diff --git a/lib/new-admin/graphql/types/blacklist.type.js b/lib/new-admin/graphql/types/blacklist.type.js index ee9ee149..7cc34721 100644 --- a/lib/new-admin/graphql/types/blacklist.type.js +++ b/lib/new-admin/graphql/types/blacklist.type.js @@ -3,15 +3,25 @@ const { gql } = require('apollo-server-express') const typeDef = gql` type Blacklist { address: String! + blacklistMessage: BlacklistMessage! + } + + type BlacklistMessage { + id: ID + label: String + content: String + allowToggle: Boolean } type Query { blacklist: [Blacklist] @auth + blacklistMessages: [BlacklistMessage] @auth } type Mutation { deleteBlacklistRow(address: String!): Blacklist @auth insertBlacklistRow(address: String!): Blacklist @auth + editBlacklistMessage(id: ID, content: String): BlacklistMessage @auth } ` diff --git a/migrations/1664916753772-advanced-blacklisting.js b/migrations/1664916753772-advanced-blacklisting.js new file mode 100644 index 00000000..915c1f33 --- /dev/null +++ b/migrations/1664916753772-advanced-blacklisting.js @@ -0,0 +1,26 @@ +const uuid = require('uuid') + +var db = require('./db') + +exports.up = function (next) { + const defaultMessageId = uuid.v4() + + var sql = [ + `CREATE TABLE blacklist_messages ( + id UUID PRIMARY KEY, + label TEXT NOT NULL, + content TEXT NOT NULL, + allow_toggle BOOLEAN NOT NULL DEFAULT true + )`, + `INSERT INTO blacklist_messages (id, label, content, allow_toggle) VALUES ('${defaultMessageId}', 'Suspicious address', 'This address may be associated with a deceptive offer or a prohibited group. Please make sure you''re using an address from your own wallet.', false)`, + `ALTER TABLE blacklist ADD COLUMN blacklist_message_id UUID REFERENCES blacklist_messages(id)`, + `UPDATE blacklist SET blacklist_message_id = '${defaultMessageId}'`, + `ALTER TABLE blacklist ALTER COLUMN blacklist_message_id SET NOT NULL` + ] + + db.multi(sql, next) +} + +exports.down = function (next) { + next() +} diff --git a/new-lamassu-admin/src/pages/Blacklist/Blacklist.js b/new-lamassu-admin/src/pages/Blacklist/Blacklist.js index 7726ddba..59c97e64 100644 --- a/new-lamassu-admin/src/pages/Blacklist/Blacklist.js +++ b/new-lamassu-admin/src/pages/Blacklist/Blacklist.js @@ -1,7 +1,6 @@ import { useQuery, useMutation } from '@apollo/react-hooks' import { addressDetector } from '@lamassu/coins' import { Box, Dialog, DialogContent, DialogActions } from '@material-ui/core' -import Grid from '@material-ui/core/Grid' import { makeStyles } from '@material-ui/core/styles' import gql from 'graphql-tag' import * as R from 'ramda' @@ -13,9 +12,12 @@ import { Switch } from 'src/components/inputs' import TitleSection from 'src/components/layout/TitleSection' import { H2, Label2, P, Info3, Info2 } from 'src/components/typography' import { ReactComponent as CloseIcon } from 'src/styling/icons/action/close/zodiac.svg' +import { ReactComponent as ReverseSettingsIcon } from 'src/styling/icons/circle buttons/settings/white.svg' +import { ReactComponent as SettingsIcon } from 'src/styling/icons/circle buttons/settings/zodiac.svg' import { fromNamespace, toNamespace } from 'src/utils/config' import styles from './Blacklist.styles' +import BlackListAdvanced from './BlacklistAdvanced' import BlackListModal from './BlacklistModal' import BlacklistTable from './BlacklistTable' @@ -33,6 +35,11 @@ const GET_BLACKLIST = gql` query getBlacklistData { blacklist { address + blacklistMessage { + id + label + content + } } cryptoCurrencies { display @@ -61,6 +68,25 @@ const ADD_ROW = gql` } ` +const GET_BLACKLIST_MESSAGES = gql` + query getBlacklistMessages { + blacklistMessages { + id + label + content + allowToggle + } + } +` + +const EDIT_BLACKLIST_MESSAGE = gql` + mutation editBlacklistMessage($id: ID, $content: String) { + editBlacklistMessage(id: $id, content: $content) { + id + } + } +` + const PaperWalletDialog = ({ onConfirmed, onDissmised, open, props }) => { const classes = useStyles() @@ -106,10 +132,13 @@ const PaperWalletDialog = ({ onConfirmed, onDissmised, open, props }) => { const Blacklist = () => { const { data: blacklistResponse } = useQuery(GET_BLACKLIST) const { data: configData } = useQuery(GET_INFO) + const { data: messagesResponse, refetch } = useQuery(GET_BLACKLIST_MESSAGES) const [showModal, setShowModal] = useState(false) const [errorMsg, setErrorMsg] = useState(null) + const [editMessageError, setEditMessageError] = useState(null) const [deleteDialog, setDeleteDialog] = useState(false) const [confirmDialog, setConfirmDialog] = useState(false) + const [advancedSettings, setAdvancedSettings] = useState(false) const [deleteEntry] = useMutation(DELETE_ROW, { onError: ({ message }) => { @@ -129,6 +158,11 @@ const Blacklist = () => { refetchQueries: () => ['getData'] }) + const [editMessage] = useMutation(EDIT_BLACKLIST_MESSAGE, { + onError: e => setEditMessageError(e), + refetchQueries: () => ['getBlacklistData'] + }) + const classes = useStyles() const blacklistData = R.path(['blacklist'])(blacklistResponse) ?? [] @@ -184,6 +218,15 @@ const Blacklist = () => { } } + const editBlacklistMessage = r => { + editMessage({ + variables: { + id: r.id, + content: r.content + } + }) + } + return ( <> { setConfirmDialog(false) }} /> - - - -

Enable paper wallet (only)

- - enablePaperWalletOnly - ? addressReuseSave({ - enablePaperWalletOnly: e.target.checked - }) - : setConfirmDialog(true) - } - value={enablePaperWalletOnly} - /> - {enablePaperWalletOnly ? 'On' : 'Off'} - -

- The "Enable paper wallet (only)" option means that only paper - wallets will be printed for users, and they won't be permitted - to scan an address from their own wallet. -

-
+ + {!advancedSettings && ( + + +

Enable paper wallet (only)

+ + enablePaperWalletOnly + ? addressReuseSave({ + enablePaperWalletOnly: e.target.checked + }) + : setConfirmDialog(true) + } + value={enablePaperWalletOnly} + /> + {enablePaperWalletOnly ? 'On' : 'Off'} + +

+ The "Enable paper wallet (only)" option means that only paper + wallets will be printed for users, and they won't be permitted + to scan an address from their own wallet. +

+
+
+ +

Reject reused addresses

+ { + addressReuseSave({ rejectAddressReuse: event.target.checked }) + }} + value={rejectAddressReuse} + /> + {rejectAddressReuse ? 'On' : 'Off'} + +

+ The "Reject reused addresses" option means that all addresses + that are used once will be automatically rejected if there's + an attempt to use them again on a new transaction. +

+
+
+ setShowModal(true)}> + Blacklist new addresses +
- -

Reject reused addresses

- { - addressReuseSave({ rejectAddressReuse: event.target.checked }) - }} - value={rejectAddressReuse} - /> - {rejectAddressReuse ? 'On' : 'Off'} - -

- The "Reject reused addresses" option means that all addresses - that are used once will be automatically rejected if there's an - attempt to use them again on a new transaction. -

-
-
- setShowModal(true)}> - Blacklist new addresses - -
+ )}
- + {!advancedSettings && (
{ setDeleteDialog={setDeleteDialog} />
-
+ )} + {advancedSettings && ( + refetch()} + /> + )} {showModal && ( { diff --git a/new-lamassu-admin/src/pages/Blacklist/Blacklist.styles.js b/new-lamassu-admin/src/pages/Blacklist/Blacklist.styles.js index 6e4a09e4..3cfc09ec 100644 --- a/new-lamassu-admin/src/pages/Blacklist/Blacklist.styles.js +++ b/new-lamassu-admin/src/pages/Blacklist/Blacklist.styles.js @@ -9,6 +9,14 @@ const styles = { flexDirection: 'column', flex: 1 }, + advancedForm: { + '& > *': { + marginTop: 20 + }, + display: 'flex', + flexDirection: 'column', + height: '100%' + }, footer: { display: 'flex', flexDirection: 'row', @@ -58,6 +66,9 @@ const styles = { cancelButton: { marginRight: 8, padding: 0 + }, + resetToDefault: { + width: 145 } } diff --git a/new-lamassu-admin/src/pages/Blacklist/BlacklistAdvanced.js b/new-lamassu-admin/src/pages/Blacklist/BlacklistAdvanced.js new file mode 100644 index 00000000..4c764b46 --- /dev/null +++ b/new-lamassu-admin/src/pages/Blacklist/BlacklistAdvanced.js @@ -0,0 +1,177 @@ +import { makeStyles } from '@material-ui/core/styles' +import { Form, Formik, Field } from 'formik' +import * as R from 'ramda' +import React, { useState } from 'react' +import * as Yup from 'yup' + +import ErrorMessage from 'src/components/ErrorMessage' +import Modal from 'src/components/Modal' +import { ActionButton, IconButton, Button } from 'src/components/buttons' +import { TextInput } from 'src/components/inputs/formik' +import DataTable from 'src/components/tables/DataTable' +import { ReactComponent as DisabledDeleteIcon } from 'src/styling/icons/action/delete/disabled.svg' +import { ReactComponent as DeleteIcon } from 'src/styling/icons/action/delete/enabled.svg' +import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/enabled.svg' +import { ReactComponent as DefaultIconReverse } from 'src/styling/icons/button/retry/white.svg' +import { ReactComponent as DefaultIcon } from 'src/styling/icons/button/retry/zodiac.svg' + +import styles from './Blacklist.styles' + +const useStyles = makeStyles(styles) + +const DEFAULT_MESSAGE = `This address may be associated with a deceptive offer or a prohibited group. Please make sure you're using an address from your own wallet.` + +const getErrorMsg = (formikErrors, formikTouched, mutationError) => { + if (!formikErrors || !formikTouched) return null + if (mutationError) return 'Internal server error' + if (formikErrors.event && formikTouched.event) return formikErrors.event + if (formikErrors.message && formikTouched.message) return formikErrors.message + return null +} + +const BlacklistAdvanced = ({ + data, + editBlacklistMessage, + onClose, + mutationError +}) => { + const classes = useStyles() + const [selectedMessage, setSelectedMessage] = useState(null) + + const elements = [ + { + name: 'label', + header: 'Label', + width: 250, + textAlign: 'left', + size: 'sm', + view: it => R.path(['label'], it) + }, + { + name: 'content', + header: 'Content', + width: 690, + textAlign: 'left', + size: 'sm', + view: it => R.path(['content'], it) + }, + { + name: 'edit', + header: 'Edit', + width: 130, + textAlign: 'center', + size: 'sm', + view: it => ( + setSelectedMessage(it)}> + + + ) + }, + { + name: 'deleteButton', + header: 'Delete', + width: 130, + textAlign: 'center', + size: 'sm', + view: it => ( + + {R.path(['allowToggle'], it) ? ( + + ) : ( + + )} + + ) + } + ] + + const handleModalClose = () => { + setSelectedMessage(null) + } + + const handleSubmit = values => { + editBlacklistMessage(values) + handleModalClose() + !R.isNil(onClose) && onClose() + } + + const initialValues = { + label: !R.isNil(selectedMessage) ? selectedMessage.label : '', + content: !R.isNil(selectedMessage) ? selectedMessage.content : '' + } + + const validationSchema = Yup.object().shape({ + label: Yup.string().required('A label is required!'), + content: Yup.string() + .required('The message content is required!') + .trim() + }) + + return ( + <> + + {selectedMessage && ( + + + handleSubmit({ id: selectedMessage.id, ...values }) + }> + {({ errors, touched, setFieldValue }) => ( +
+ setFieldValue('content', DEFAULT_MESSAGE)}> + Reset to default + + +
+ {getErrorMsg(errors, touched, mutationError) && ( + + {getErrorMsg(errors, touched, mutationError)} + + )} + +
+ + )} +
+
+ )} + + ) +} + +export default BlacklistAdvanced From 677cb39f0c4433630adc34096a7d59255a293ade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Salgado?= Date: Thu, 6 Oct 2022 19:03:00 +0100 Subject: [PATCH 03/14] feat: add blacklist message to machine communication --- lib/blacklist.js | 2 +- lib/cash-in/cash-in-low.js | 2 +- lib/cash-in/cash-in-tx.js | 7 ++++--- migrations/1664916753772-advanced-blacklisting.js | 4 +--- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/blacklist.js b/lib/blacklist.js index 89a9037f..79835f10 100644 --- a/lib/blacklist.js +++ b/lib/blacklist.js @@ -26,7 +26,7 @@ const insertIntoBlacklist = address => { } function blocked (address) { - const sql = `SELECT * FROM blacklist WHERE address = $1` + const sql = `SELECT address, content FROM blacklist b LEFT OUTER JOIN blacklist_messages bm ON bm.id = b.blacklist_message_id WHERE address = $1` return db.any(sql, [address]) } diff --git a/lib/cash-in/cash-in-low.js b/lib/cash-in/cash-in-low.js index 5b8066a0..0f2942df 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 massageFields = ['direction', 'cryptoNetwork', 'bills', 'blacklisted', 'addressReuse', 'promoCodeApplied', 'validWalletScore', 'cashInFeeCrypto'] +const massageFields = ['direction', 'cryptoNetwork', 'bills', 'blacklisted', 'blacklistMessage', 'addressReuse', 'promoCodeApplied', 'validWalletScore', 'cashInFeeCrypto'] const massageUpdateFields = _.concat(massageFields, 'cryptoAtoms') const massage = _.flow(_.omit(massageFields), diff --git a/lib/cash-in/cash-in-tx.js b/lib/cash-in/cash-in-tx.js index 5123eeb6..2f301cc5 100644 --- a/lib/cash-in/cash-in-tx.js +++ b/lib/cash-in/cash-in-tx.js @@ -32,7 +32,7 @@ function post (machineTx, pi) { return cashInAtomic.atomic(machineTx, pi) .then(r => { const updatedTx = r.tx - let blacklisted = false + let blacklisted = null let addressReuse = false let walletScore = {} @@ -50,7 +50,7 @@ function post (machineTx, pi) { walletScore = fetchedWalletScore if (_.some(it => it.address === updatedTx.toAddress)(blacklistItems)) { - blacklisted = true + blacklisted = _.find(it => it.address === updatedTx.toAddress)(blacklistItems) notifier.notifyIfActive('compliance', 'blacklistNotify', r.tx, false) } else if (isReusedAddress && rejectAddressReuse) { notifier.notifyIfActive('compliance', 'blacklistNotify', r.tx, true) @@ -61,7 +61,8 @@ function post (machineTx, pi) { .then(changes => _.set('walletScore', _.isNil(walletScore) ? null : walletScore.score, changes)) .then(changes => cashInLow.update(db, updatedTx, changes)) .then(tx => _.set('bills', machineTx.bills, tx)) - .then(tx => _.set('blacklisted', blacklisted, tx)) + .then(tx => _.set('blacklisted', Boolean(blacklisted), tx)) + .then(tx => _.set('blacklistMessage', blacklisted?.content, tx)) .then(tx => _.set('addressReuse', addressReuse, tx)) .then(tx => _.set('validWalletScore', _.isNil(walletScore) ? true : walletScore.isValid, tx)) }) diff --git a/migrations/1664916753772-advanced-blacklisting.js b/migrations/1664916753772-advanced-blacklisting.js index 915c1f33..4648f182 100644 --- a/migrations/1664916753772-advanced-blacklisting.js +++ b/migrations/1664916753772-advanced-blacklisting.js @@ -13,9 +13,7 @@ exports.up = function (next) { allow_toggle BOOLEAN NOT NULL DEFAULT true )`, `INSERT INTO blacklist_messages (id, label, content, allow_toggle) VALUES ('${defaultMessageId}', 'Suspicious address', 'This address may be associated with a deceptive offer or a prohibited group. Please make sure you''re using an address from your own wallet.', false)`, - `ALTER TABLE blacklist ADD COLUMN blacklist_message_id UUID REFERENCES blacklist_messages(id)`, - `UPDATE blacklist SET blacklist_message_id = '${defaultMessageId}'`, - `ALTER TABLE blacklist ALTER COLUMN blacklist_message_id SET NOT NULL` + `ALTER TABLE blacklist ADD COLUMN blacklist_message_id UUID REFERENCES blacklist_messages(id) NOT NULL DEFAULT '${defaultMessageId}'` ] db.multi(sql, next) From 01303d6454e7a98c3d4ef5e702c8eec93183ed8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Salgado?= Date: Sat, 15 Oct 2022 04:07:30 +0100 Subject: [PATCH 04/14] fix: clean up code --- lib/blacklist.js | 10 +--------- lib/cash-in/cash-in-tx.js | 15 +++++++++------ .../src/pages/Blacklist/Blacklist.js | 5 ----- .../src/pages/Blacklist/BlacklistAdvanced.js | 5 +++-- 4 files changed, 13 insertions(+), 22 deletions(-) diff --git a/lib/blacklist.js b/lib/blacklist.js index 79835f10..63a7fb13 100644 --- a/lib/blacklist.js +++ b/lib/blacklist.js @@ -27,15 +27,8 @@ const insertIntoBlacklist = address => { function blocked (address) { const sql = `SELECT address, content FROM blacklist b LEFT OUTER JOIN blacklist_messages bm ON bm.id = b.blacklist_message_id WHERE address = $1` - return db.any(sql, [address]) -} - -function addToUsedAddresses (address) { - // ETH reuses addresses - // if (cryptoCode === 'ETH') return Promise.resolve() - - const sql = `INSERT INTO blacklist (address) VALUES ($1)` return db.oneOrNone(sql, [address]) + .then(r => !_.isNil(r)) } function getMessages () { @@ -50,7 +43,6 @@ function editBlacklistMessage (id, content) { module.exports = { blocked, - addToUsedAddresses, getBlacklist, deleteFromBlacklist, insertIntoBlacklist, diff --git a/lib/cash-in/cash-in-tx.js b/lib/cash-in/cash-in-tx.js index 2f301cc5..f321e8fe 100644 --- a/lib/cash-in/cash-in-tx.js +++ b/lib/cash-in/cash-in-tx.js @@ -40,28 +40,31 @@ function post (machineTx, pi) { const isFirstPost = !r.tx.fiat || r.tx.fiat.isZero() if (isFirstPost) { - promises.push(checkForBlacklisted(updatedTx), doesTxReuseAddress(updatedTx), getWalletScore(updatedTx, pi)) + promises.push( + checkForBlacklisted(updatedTx), + doesTxReuseAddress(updatedTx), + getWalletScore(updatedTx, pi) + ) } return Promise.all(promises) - .then(([config, blacklistItems = false, isReusedAddress = false, fetchedWalletScore = null]) => { + .then(([config, isBlacklisted = false, isReusedAddress = false, fetchedWalletScore = null]) => { const rejectAddressReuse = configManager.getCompliance(config).rejectAddressReuse walletScore = fetchedWalletScore - if (_.some(it => it.address === updatedTx.toAddress)(blacklistItems)) { - blacklisted = _.find(it => it.address === updatedTx.toAddress)(blacklistItems) + if (isBlacklisted) { notifier.notifyIfActive('compliance', 'blacklistNotify', r.tx, false) } else if (isReusedAddress && rejectAddressReuse) { notifier.notifyIfActive('compliance', 'blacklistNotify', r.tx, true) addressReuse = true } - return postProcess(r, pi, blacklisted, addressReuse, walletScore) + return postProcess(r, pi, isBlacklisted, addressReuse, walletScore) }) .then(changes => _.set('walletScore', _.isNil(walletScore) ? null : walletScore.score, changes)) .then(changes => cashInLow.update(db, updatedTx, changes)) .then(tx => _.set('bills', machineTx.bills, tx)) - .then(tx => _.set('blacklisted', Boolean(blacklisted), tx)) + .then(tx => _.set('blacklisted', isBlacklisted, tx)) .then(tx => _.set('blacklistMessage', blacklisted?.content, tx)) .then(tx => _.set('addressReuse', addressReuse, tx)) .then(tx => _.set('validWalletScore', _.isNil(walletScore) ? true : walletScore.isValid, tx)) diff --git a/new-lamassu-admin/src/pages/Blacklist/Blacklist.js b/new-lamassu-admin/src/pages/Blacklist/Blacklist.js index 59c97e64..0ca8c509 100644 --- a/new-lamassu-admin/src/pages/Blacklist/Blacklist.js +++ b/new-lamassu-admin/src/pages/Blacklist/Blacklist.js @@ -35,11 +35,6 @@ const GET_BLACKLIST = gql` query getBlacklistData { blacklist { address - blacklistMessage { - id - label - content - } } cryptoCurrencies { display diff --git a/new-lamassu-admin/src/pages/Blacklist/BlacklistAdvanced.js b/new-lamassu-admin/src/pages/Blacklist/BlacklistAdvanced.js index 4c764b46..f3790959 100644 --- a/new-lamassu-admin/src/pages/Blacklist/BlacklistAdvanced.js +++ b/new-lamassu-admin/src/pages/Blacklist/BlacklistAdvanced.js @@ -22,8 +22,8 @@ const useStyles = makeStyles(styles) const DEFAULT_MESSAGE = `This address may be associated with a deceptive offer or a prohibited group. Please make sure you're using an address from your own wallet.` const getErrorMsg = (formikErrors, formikTouched, mutationError) => { - if (!formikErrors || !formikTouched) return null if (mutationError) return 'Internal server error' + if (!formikErrors || !formikTouched) return null if (formikErrors.event && formikTouched.event) return formikErrors.event if (formikErrors.message && formikTouched.message) return formikErrors.message return null @@ -79,7 +79,8 @@ const BlacklistAdvanced = ({ {R.path(['allowToggle'], it) ? ( From a6078689421786f06e1b5f3c29532fa32ea315d4 Mon Sep 17 00:00:00 2001 From: siiky Date: Fri, 16 Dec 2022 12:32:38 +0000 Subject: [PATCH 05/14] fix: syntax error in migration file --- migrations/1664907000312-coin-agnostic-blacklist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/1664907000312-coin-agnostic-blacklist.js b/migrations/1664907000312-coin-agnostic-blacklist.js index 9cd78a5f..9a227308 100644 --- a/migrations/1664907000312-coin-agnostic-blacklist.js +++ b/migrations/1664907000312-coin-agnostic-blacklist.js @@ -4,7 +4,7 @@ exports.up = function (next) { var sql = [ `CREATE TABLE blacklist_temp ( address TEXT NOT NULL UNIQUE - )` + )`, `INSERT INTO blacklist_temp (address) SELECT DISTINCT address FROM blacklist`, `DROP TABLE blacklist`, `ALTER TABLE blacklist_temp RENAME TO blacklist` From 4793b2a415053528b4a364b17282c9829dd17af7 Mon Sep 17 00:00:00 2001 From: siiky Date: Fri, 16 Dec 2022 12:41:14 +0000 Subject: [PATCH 06/14] refactor: join in the DB --- lib/blacklist.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/blacklist.js b/lib/blacklist.js index 63a7fb13..2a34a1f2 100644 --- a/lib/blacklist.js +++ b/lib/blacklist.js @@ -3,13 +3,12 @@ const _ = require('lodash/fp') const db = require('./db') const notifierQueries = require('./notifier/queries') -const getBlacklist = () => { - const blacklistSql = `SELECT * FROM blacklist` - const messagesSql = `SELECT * FROM blacklist_messages` - return Promise.all([db.any(blacklistSql), db.any(messagesSql)]) - .then(([blacklist, messages]) => Promise.all([_.map(_.mapKeys(_.camelCase), blacklist), _.map(_.mapKeys(_.camelCase), messages)])) - .then(([blacklist, messages]) => _.map(it => ({ ...it, blacklistMessage: _.find(ite => it.blacklistMessageId === ite.id, messages) }), blacklist)) -} +const getBlacklist = () => + db.any( + `SELECT blacklist.address AS address, blacklist_messages.content AS blacklistMessage + FROM blacklist JOIN blacklist_messages + ON blacklist.blacklist_message_id = blacklist_messages.id` + ) const deleteFromBlacklist = address => { const sql = `DELETE FROM blacklist WHERE address = $1` From 7f2651fa9ec53c70d451044cf0fca1ee0b1211b8 Mon Sep 17 00:00:00 2001 From: siiky Date: Fri, 16 Dec 2022 16:58:33 +0000 Subject: [PATCH 07/14] fix: undefined variable --- lib/cash-in/cash-in-tx.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/cash-in/cash-in-tx.js b/lib/cash-in/cash-in-tx.js index f321e8fe..8ebdcf20 100644 --- a/lib/cash-in/cash-in-tx.js +++ b/lib/cash-in/cash-in-tx.js @@ -60,14 +60,14 @@ function post (machineTx, pi) { addressReuse = true } return postProcess(r, pi, isBlacklisted, addressReuse, walletScore) + .then(changes => _.set('walletScore', _.isNil(walletScore) ? null : walletScore.score, changes)) + .then(changes => cashInLow.update(db, updatedTx, changes)) + .then(tx => _.set('bills', machineTx.bills, tx)) + .then(tx => _.set('blacklisted', isBlacklisted, tx)) + .then(tx => _.set('blacklistMessage', blacklisted?.content, tx)) + .then(tx => _.set('addressReuse', addressReuse, tx)) + .then(tx => _.set('validWalletScore', _.isNil(walletScore) ? true : walletScore.isValid, tx)) }) - .then(changes => _.set('walletScore', _.isNil(walletScore) ? null : walletScore.score, changes)) - .then(changes => cashInLow.update(db, updatedTx, changes)) - .then(tx => _.set('bills', machineTx.bills, tx)) - .then(tx => _.set('blacklisted', isBlacklisted, tx)) - .then(tx => _.set('blacklistMessage', blacklisted?.content, tx)) - .then(tx => _.set('addressReuse', addressReuse, tx)) - .then(tx => _.set('validWalletScore', _.isNil(walletScore) ? true : walletScore.isValid, tx)) }) } From f010398ebf34b4cb99f1bc31131c9036e7a92790 Mon Sep 17 00:00:00 2001 From: siiky Date: Fri, 16 Dec 2022 17:00:28 +0000 Subject: [PATCH 08/14] refactor: replace `then` chain with `flow` --- lib/cash-in/cash-in-tx.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/cash-in/cash-in-tx.js b/lib/cash-in/cash-in-tx.js index 8ebdcf20..8d046834 100644 --- a/lib/cash-in/cash-in-tx.js +++ b/lib/cash-in/cash-in-tx.js @@ -62,11 +62,13 @@ function post (machineTx, pi) { return postProcess(r, pi, isBlacklisted, addressReuse, walletScore) .then(changes => _.set('walletScore', _.isNil(walletScore) ? null : walletScore.score, changes)) .then(changes => cashInLow.update(db, updatedTx, changes)) - .then(tx => _.set('bills', machineTx.bills, tx)) - .then(tx => _.set('blacklisted', isBlacklisted, tx)) - .then(tx => _.set('blacklistMessage', blacklisted?.content, tx)) - .then(tx => _.set('addressReuse', addressReuse, tx)) - .then(tx => _.set('validWalletScore', _.isNil(walletScore) ? true : walletScore.isValid, tx)) + .then(_.flow( + _.set('bills', machineTx.bills), + _.set('blacklisted', isBlacklisted), + _.set('blacklistMessage', blacklisted?.content), + _.set('addressReuse', addressReuse), + _.set('validWalletScore', _.isNil(walletScore) ? true : walletScore.isValid), + )) }) }) } From 944ef60121323e41d74e11e08276fb3cb7a55330 Mon Sep 17 00:00:00 2001 From: siiky Date: Fri, 16 Dec 2022 17:03:26 +0000 Subject: [PATCH 09/14] refactor: remove unnecessary variable --- lib/cash-in/cash-in-tx.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/cash-in/cash-in-tx.js b/lib/cash-in/cash-in-tx.js index 8d046834..64afaa7f 100644 --- a/lib/cash-in/cash-in-tx.js +++ b/lib/cash-in/cash-in-tx.js @@ -34,7 +34,6 @@ function post (machineTx, pi) { const updatedTx = r.tx let blacklisted = null let addressReuse = false - let walletScore = {} const promises = [settingsLoader.loadLatestConfig()] @@ -48,11 +47,9 @@ function post (machineTx, pi) { } return Promise.all(promises) - .then(([config, isBlacklisted = false, isReusedAddress = false, fetchedWalletScore = null]) => { + .then(([config, isBlacklisted = false, isReusedAddress = false, walletScore = null]) => { const rejectAddressReuse = configManager.getCompliance(config).rejectAddressReuse - walletScore = fetchedWalletScore - if (isBlacklisted) { notifier.notifyIfActive('compliance', 'blacklistNotify', r.tx, false) } else if (isReusedAddress && rejectAddressReuse) { From e1811daf24ffe7701f47da9f8947adfa6b68d38f Mon Sep 17 00:00:00 2001 From: siiky Date: Fri, 16 Dec 2022 17:03:45 +0000 Subject: [PATCH 10/14] refactor: use restructuring --- lib/cash-in/cash-in-tx.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cash-in/cash-in-tx.js b/lib/cash-in/cash-in-tx.js index 64afaa7f..03235176 100644 --- a/lib/cash-in/cash-in-tx.js +++ b/lib/cash-in/cash-in-tx.js @@ -48,7 +48,7 @@ function post (machineTx, pi) { return Promise.all(promises) .then(([config, isBlacklisted = false, isReusedAddress = false, walletScore = null]) => { - const rejectAddressReuse = configManager.getCompliance(config).rejectAddressReuse + const { rejectAddressReuse } = configManager.getCompliance(config) if (isBlacklisted) { notifier.notifyIfActive('compliance', 'blacklistNotify', r.tx, false) From a56336282f2faee8c795dee8f81b8d14efd252b1 Mon Sep 17 00:00:00 2001 From: siiky Date: Fri, 16 Dec 2022 17:24:13 +0000 Subject: [PATCH 11/14] fix: get blacklist message associated with address --- lib/blacklist.js | 1 - lib/cash-in/cash-in-tx.js | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/blacklist.js b/lib/blacklist.js index 2a34a1f2..8324fc20 100644 --- a/lib/blacklist.js +++ b/lib/blacklist.js @@ -27,7 +27,6 @@ const insertIntoBlacklist = address => { function blocked (address) { const sql = `SELECT address, content FROM blacklist b LEFT OUTER JOIN blacklist_messages bm ON bm.id = b.blacklist_message_id WHERE address = $1` return db.oneOrNone(sql, [address]) - .then(r => !_.isNil(r)) } function getMessages () { diff --git a/lib/cash-in/cash-in-tx.js b/lib/cash-in/cash-in-tx.js index 03235176..09d0a235 100644 --- a/lib/cash-in/cash-in-tx.js +++ b/lib/cash-in/cash-in-tx.js @@ -32,7 +32,6 @@ function post (machineTx, pi) { return cashInAtomic.atomic(machineTx, pi) .then(r => { const updatedTx = r.tx - let blacklisted = null let addressReuse = false const promises = [settingsLoader.loadLatestConfig()] @@ -47,8 +46,9 @@ function post (machineTx, pi) { } return Promise.all(promises) - .then(([config, isBlacklisted = false, isReusedAddress = false, walletScore = null]) => { + .then(([config, blacklisted = false, isReusedAddress = false, walletScore = null]) => { const { rejectAddressReuse } = configManager.getCompliance(config) + const isBlacklisted = !!blacklisted if (isBlacklisted) { notifier.notifyIfActive('compliance', 'blacklistNotify', r.tx, false) From 63bb2c791d95fe2dce83c9433728678f779be256 Mon Sep 17 00:00:00 2001 From: siiky Date: Fri, 16 Dec 2022 17:35:19 +0000 Subject: [PATCH 12/14] refactor: replace ternary operator with binary OR operator --- lib/cash-in/cash-in-tx.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cash-in/cash-in-tx.js b/lib/cash-in/cash-in-tx.js index 09d0a235..a4e8c228 100644 --- a/lib/cash-in/cash-in-tx.js +++ b/lib/cash-in/cash-in-tx.js @@ -64,7 +64,7 @@ function post (machineTx, pi) { _.set('blacklisted', isBlacklisted), _.set('blacklistMessage', blacklisted?.content), _.set('addressReuse', addressReuse), - _.set('validWalletScore', _.isNil(walletScore) ? true : walletScore.isValid), + _.set('validWalletScore', _.isNil(walletScore) || walletScore.isValid), )) }) }) From bcfa108f0d0b17d17f62f64b0954ba5841cf8942 Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 29 Nov 2024 11:58:40 +0000 Subject: [PATCH 13/14] chore: update time of migration --- ...stic-blacklist.js => 1732881489395-coin-agnostic-blacklist.js} | 0 ...ced-blacklisting.js => 1732881489396-advanced-blacklisting.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename migrations/{1664907000312-coin-agnostic-blacklist.js => 1732881489395-coin-agnostic-blacklist.js} (100%) rename migrations/{1664916753772-advanced-blacklisting.js => 1732881489396-advanced-blacklisting.js} (100%) diff --git a/migrations/1664907000312-coin-agnostic-blacklist.js b/migrations/1732881489395-coin-agnostic-blacklist.js similarity index 100% rename from migrations/1664907000312-coin-agnostic-blacklist.js rename to migrations/1732881489395-coin-agnostic-blacklist.js diff --git a/migrations/1664916753772-advanced-blacklisting.js b/migrations/1732881489396-advanced-blacklisting.js similarity index 100% rename from migrations/1664916753772-advanced-blacklisting.js rename to migrations/1732881489396-advanced-blacklisting.js From 5881fe5d9c99f047bb03a9d9a9a60ed09c7804c1 Mon Sep 17 00:00:00 2001 From: Nikola Ubavic <53820106+ubavic@users.noreply.github.com> Date: Thu, 26 Jan 2023 14:47:06 +0100 Subject: [PATCH 14/14] fix: undefined address --- new-lamassu-admin/src/pages/Blacklist/BlacklistTable.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/new-lamassu-admin/src/pages/Blacklist/BlacklistTable.js b/new-lamassu-admin/src/pages/Blacklist/BlacklistTable.js index 39bcb1ab..9e929a0c 100644 --- a/new-lamassu-admin/src/pages/Blacklist/BlacklistTable.js +++ b/new-lamassu-admin/src/pages/Blacklist/BlacklistTable.js @@ -72,10 +72,7 @@ const BlacklistTable = ({ }} onConfirmed={() => { setErrorMessage(null) - handleDeleteEntry( - R.path(['cryptoCode'], toBeDeleted), - R.path(['address'], toBeDeleted) - ) + handleDeleteEntry(R.path(['address'], toBeDeleted)) }} errorMessage={errorMessage} />