feat: reject address reuse
This commit is contained in:
parent
f2080c32e9
commit
f6547341f1
5 changed files with 69 additions and 27 deletions
|
|
@ -7,7 +7,7 @@ const db = require('../db')
|
||||||
const plugins = require('../plugins')
|
const plugins = require('../plugins')
|
||||||
const logger = require('../logger')
|
const logger = require('../logger')
|
||||||
const settingsLoader = require('../new-settings-loader')
|
const settingsLoader = require('../new-settings-loader')
|
||||||
// const configManager = require('../new-config-manager')
|
const configManager = require('../new-config-manager')
|
||||||
|
|
||||||
const cashInAtomic = require('./cash-in-atomic')
|
const cashInAtomic = require('./cash-in-atomic')
|
||||||
const cashInLow = require('./cash-in-low')
|
const cashInLow = require('./cash-in-low')
|
||||||
|
|
@ -26,9 +26,7 @@ function post (machineTx, pi) {
|
||||||
|
|
||||||
return Promise.all([settingsLoader.loadLatest(), checkForBlacklisted(updatedTx)])
|
return Promise.all([settingsLoader.loadLatest(), checkForBlacklisted(updatedTx)])
|
||||||
.then(([{ config }, blacklistItems]) => {
|
.then(([{ config }, blacklistItems]) => {
|
||||||
// TODO new-admin: addressReuse doesnt exist
|
const rejectAddressReuseActive = configManager.getCompliance(config).rejectAddressReuse
|
||||||
// const rejectAddressReuseActive = configManager.unscoped(config).rejectAddressReuseActive
|
|
||||||
const rejectAddressReuseActive = false
|
|
||||||
|
|
||||||
if (_.some(it => it.created_by_operator === true)(blacklistItems)) {
|
if (_.some(it => it.created_by_operator === true)(blacklistItems)) {
|
||||||
blacklisted = true
|
blacklisted = true
|
||||||
|
|
@ -125,9 +123,8 @@ function postProcess (r, pi, isBlacklisted, addressReuse) {
|
||||||
})
|
})
|
||||||
.then(sendRec => {
|
.then(sendRec => {
|
||||||
settingsLoader.loadLatest().then(it => {
|
settingsLoader.loadLatest().then(it => {
|
||||||
// TODO new-admin: addressReuse doesnt exist
|
const rejectAddressReuseActive = configManager.getCompliance(it.config).rejectAddressReuse
|
||||||
// const config = configManager.unscoped(it.config)
|
if (rejectAddressReuseActive) {
|
||||||
if (false) {
|
|
||||||
blacklist.addToUsedAddresses(r.tx.toAddress, r.tx.cryptoCode)
|
blacklist.addToUsedAddresses(r.tx.toAddress, r.tx.cryptoCode)
|
||||||
.catch(err => logger.error('Failure adding to addressReuse', err))
|
.catch(err => logger.error('Failure adding to addressReuse', err))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@ const namespaces = {
|
||||||
RECEIPT: 'receipt',
|
RECEIPT: 'receipt',
|
||||||
COIN_ATM_RADAR: 'coinAtmRadar',
|
COIN_ATM_RADAR: 'coinAtmRadar',
|
||||||
TERMS_CONDITIONS: 'termsConditions',
|
TERMS_CONDITIONS: 'termsConditions',
|
||||||
CASH_OUT: 'cashOut'
|
CASH_OUT: 'cashOut',
|
||||||
|
COMPLIANCE: 'compliance'
|
||||||
}
|
}
|
||||||
|
|
||||||
const stripl = _.curry((q, str) => _.startsWith(q, str) ? str.slice(q.length) : str)
|
const stripl = _.curry((q, str) => _.startsWith(q, str) ? str.slice(q.length) : str)
|
||||||
|
|
@ -48,6 +49,7 @@ const getOperatorInfo = fromNamespace(namespaces.OPERATOR_INFO)
|
||||||
const getCoinAtmRadar = fromNamespace(namespaces.COIN_ATM_RADAR)
|
const getCoinAtmRadar = fromNamespace(namespaces.COIN_ATM_RADAR)
|
||||||
const getTermsConditions = fromNamespace(namespaces.TERMS_CONDITIONS)
|
const getTermsConditions = fromNamespace(namespaces.TERMS_CONDITIONS)
|
||||||
const getReceipt = fromNamespace(namespaces.RECEIPT)
|
const getReceipt = fromNamespace(namespaces.RECEIPT)
|
||||||
|
const getCompliance = fromNamespace(namespaces.COMPLIANCE)
|
||||||
|
|
||||||
const getAllCryptoCurrencies = (config) => {
|
const getAllCryptoCurrencies = (config) => {
|
||||||
const locale = fromNamespace(namespaces.LOCALE)(config)
|
const locale = fromNamespace(namespaces.LOCALE)(config)
|
||||||
|
|
@ -85,6 +87,7 @@ module.exports = {
|
||||||
getGlobalLocale,
|
getGlobalLocale,
|
||||||
getCommissions,
|
getCommissions,
|
||||||
getReceipt,
|
getReceipt,
|
||||||
|
getCompliance,
|
||||||
getCoinAtmRadar,
|
getCoinAtmRadar,
|
||||||
getTermsConditions,
|
getTermsConditions,
|
||||||
getAllCryptoCurrencies,
|
getAllCryptoCurrencies,
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,18 @@ function plugins (settings, deviceId) {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLcmOrBigx2 (n1, n2) {
|
||||||
|
let big = Math.max(n1, n2);
|
||||||
|
let small = Math.min(n1, n2);
|
||||||
|
|
||||||
|
let i = big * 2;
|
||||||
|
while(i % small !== 0){
|
||||||
|
i += lar;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
function buildAvailableCassettes (excludeTxId) {
|
function buildAvailableCassettes (excludeTxId) {
|
||||||
const cashOutConfig = configManager.getCashOut(deviceId, settings.config)
|
const cashOutConfig = configManager.getCashOut(deviceId, settings.config)
|
||||||
|
|
||||||
|
|
@ -131,8 +143,7 @@ function plugins (settings, deviceId) {
|
||||||
|
|
||||||
const denominations = [cashOutConfig.top, cashOutConfig.bottom]
|
const denominations = [cashOutConfig.top, cashOutConfig.bottom]
|
||||||
|
|
||||||
// TODO new-admin: will this actually be calculated?
|
const virtualCassettes = [getLcmOrBigx2(cashOutConfig.top, cashOutConfig.bottom)]
|
||||||
const virtualCassettes = [cashOutConfig.top + cashOutConfig.bottom]
|
|
||||||
|
|
||||||
return Promise.all([dbm.cassetteCounts(deviceId), cashOutHelper.redeemableTxs(deviceId, excludeTxId)])
|
return Promise.all([dbm.cassetteCounts(deviceId), cashOutHelper.redeemableTxs(deviceId, excludeTxId)])
|
||||||
.then(([rec, _redeemableTxs]) => {
|
.then(([rec, _redeemableTxs]) => {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ const useStyles = makeStyles({
|
||||||
border: 'none',
|
border: 'none',
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
marginTop: 4,
|
marginTop: 4,
|
||||||
|
outline: 'none',
|
||||||
cursor: 'pointer'
|
cursor: 'pointer'
|
||||||
},
|
},
|
||||||
popoverContent: ({ width }) => ({
|
popoverContent: ({ width }) => ({
|
||||||
|
|
@ -33,18 +34,19 @@ const Tooltip = memo(({ children, width, Icon = HelpIcon }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ClickAwayListener onClickAway={handleCloseHelpPopper}>
|
<ClickAwayListener onClickAway={handleCloseHelpPopper}>
|
||||||
<button
|
<div>
|
||||||
className={classes.transparentButton}
|
<button
|
||||||
onClick={handleOpenHelpPopper}>
|
className={classes.transparentButton}
|
||||||
<Icon />
|
onClick={handleOpenHelpPopper}>
|
||||||
|
<Icon />
|
||||||
|
</button>
|
||||||
<Popper
|
<Popper
|
||||||
open={helpPopperOpen}
|
open={helpPopperOpen}
|
||||||
anchorEl={helpPopperAnchorEl}
|
anchorEl={helpPopperAnchorEl}
|
||||||
placement="bottom"
|
placement="bottom">
|
||||||
onClose={handleCloseHelpPopper}>
|
|
||||||
<div className={classes.popoverContent}>{children}</div>
|
<div className={classes.popoverContent}>{children}</div>
|
||||||
</Popper>
|
</Popper>
|
||||||
</button>
|
</div>
|
||||||
</ClickAwayListener>
|
</ClickAwayListener>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,17 @@
|
||||||
import { useQuery, useMutation } from '@apollo/react-hooks'
|
import { useQuery, useMutation } from '@apollo/react-hooks'
|
||||||
import { makeStyles } from '@material-ui/core'
|
import { makeStyles, Box } from '@material-ui/core'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { v4 } from 'uuid'
|
import { v4 } from 'uuid'
|
||||||
|
|
||||||
import Title from 'src/components/Title'
|
import Tooltip from 'src/components/Tooltip'
|
||||||
import { Link } from 'src/components/buttons'
|
import { Link } from 'src/components/buttons'
|
||||||
import { Table as EditableTable } from 'src/components/editableTable'
|
import { Table as EditableTable } from 'src/components/editableTable'
|
||||||
import { fromNamespace, namespaces } from 'src/utils/config'
|
import { Switch } from 'src/components/inputs'
|
||||||
|
import TitleSection from 'src/components/layout/TitleSection'
|
||||||
|
import { P, Label2 } from 'src/components/typography'
|
||||||
|
import { fromNamespace, toNamespace, namespaces } from 'src/utils/config'
|
||||||
|
|
||||||
import { mainStyles } from './Triggers.styles'
|
import { mainStyles } from './Triggers.styles'
|
||||||
import Wizard from './Wizard'
|
import Wizard from './Wizard'
|
||||||
|
|
@ -36,6 +39,10 @@ const Triggers = () => {
|
||||||
const { data } = useQuery(GET_INFO)
|
const { data } = useQuery(GET_INFO)
|
||||||
const triggers = fromServer(data?.config?.triggers ?? [])
|
const triggers = fromServer(data?.config?.triggers ?? [])
|
||||||
|
|
||||||
|
const complianceConfig =
|
||||||
|
data?.config && fromNamespace('compliance')(data.config)
|
||||||
|
const rejectAddressReuse = complianceConfig?.rejectAddressReuse ?? false
|
||||||
|
|
||||||
const [saveConfig] = useMutation(SAVE_CONFIG, {
|
const [saveConfig] = useMutation(SAVE_CONFIG, {
|
||||||
onCompleted: () => setWizard(false),
|
onCompleted: () => setWizard(false),
|
||||||
onError: () => setError(true),
|
onError: () => setError(true),
|
||||||
|
|
@ -48,6 +55,11 @@ const Triggers = () => {
|
||||||
return saveConfig({ variables: { config: { triggers: toServer(toSave) } } })
|
return saveConfig({ variables: { config: { triggers: toServer(toSave) } } })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const addressReuseSave = rawConfig => {
|
||||||
|
const config = toNamespace('compliance')(rawConfig)
|
||||||
|
return saveConfig({ variables: { config } })
|
||||||
|
}
|
||||||
|
|
||||||
const save = config => {
|
const save = config => {
|
||||||
setError(false)
|
setError(false)
|
||||||
return saveConfig({
|
return saveConfig({
|
||||||
|
|
@ -61,16 +73,33 @@ const Triggers = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={classes.titleWrapper}>
|
<TitleSection title="Compliance Triggers">
|
||||||
<div className={classes.titleAndButtonsContainer}>
|
<Box display="flex" alignItems="center">
|
||||||
<Title>Compliance Triggers</Title>
|
<Box display="flex" alignItems="center" justifyContent="end" mr={3}>
|
||||||
</div>
|
<P>Reject reused addresses</P>
|
||||||
<div className={classes.headerLabels}>
|
<Switch
|
||||||
|
checked={rejectAddressReuse}
|
||||||
|
onChange={event => {
|
||||||
|
addressReuseSave({ rejectAddressReuse: event.target.checked })
|
||||||
|
}}
|
||||||
|
value={rejectAddressReuse}
|
||||||
|
/>
|
||||||
|
<Label2 className={classes.switchLabel}>
|
||||||
|
{rejectAddressReuse ? 'On' : 'Off'}
|
||||||
|
</Label2>
|
||||||
|
<Tooltip width={304}>
|
||||||
|
<P>
|
||||||
|
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.
|
||||||
|
</P>
|
||||||
|
</Tooltip>
|
||||||
|
</Box>
|
||||||
<Link color="primary" onClick={() => setWizard(true)}>
|
<Link color="primary" onClick={() => setWizard(true)}>
|
||||||
+ Add new trigger
|
+ Add new trigger
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</Box>
|
||||||
</div>
|
</TitleSection>
|
||||||
<EditableTable
|
<EditableTable
|
||||||
data={triggers}
|
data={triggers}
|
||||||
name="triggers"
|
name="triggers"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue