fix: transaction screens fixes
This commit is contained in:
parent
bf8f1d991c
commit
8f7bb412a1
12 changed files with 315 additions and 37 deletions
46
TODO.json
Normal file
46
TODO.json
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"code": "balanceAlerts",
|
||||||
|
"fields": [
|
||||||
|
"cashInAlertThreshold"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "compliance",
|
||||||
|
"fields": [
|
||||||
|
"smsVerificationActive",
|
||||||
|
"smsVerificationThreshold",
|
||||||
|
"idCardDataVerificationActive",
|
||||||
|
"idCardDataVerificationThreshold",
|
||||||
|
"idCardPhotoVerificationActive",
|
||||||
|
"idCardPhotoVerificationThreshold",
|
||||||
|
"sanctionsVerificationActive",
|
||||||
|
"sanctionsVerificationThreshold",
|
||||||
|
"frontCameraVerificationActive",
|
||||||
|
"frontCameraVerificationThreshold",
|
||||||
|
"hardLimitVerificationActive",
|
||||||
|
"hardLimitVerificationThreshold",
|
||||||
|
"receiptPrintingActive",
|
||||||
|
"rejectAddressReuseActive"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "walletSettings",
|
||||||
|
"fields": [
|
||||||
|
"ticker",
|
||||||
|
"wallet",
|
||||||
|
"layer2",
|
||||||
|
"exchange",
|
||||||
|
"zeroConf"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "notifications",
|
||||||
|
"fields": [
|
||||||
|
"sms",
|
||||||
|
"email"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -62,7 +62,10 @@ function batch () {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCustomerTransactions (customerId) {
|
function getCustomerTransactions (customerId) {
|
||||||
const packager = _.flow(_.flatten, _.orderBy(_.property('created'), ['desc']),
|
const packager = _.flow(it => {
|
||||||
|
console.log()
|
||||||
|
return it
|
||||||
|
}, _.flatten, _.orderBy(_.property('created'), ['desc']),
|
||||||
_.take(NUM_RESULTS), _.map(camelize), addNames)
|
_.take(NUM_RESULTS), _.map(camelize), addNames)
|
||||||
|
|
||||||
const cashInSql = `select 'cashIn' as tx_class, txs.*,
|
const cashInSql = `select 'cashIn' as tx_class, txs.*,
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,7 @@ function plugins (settings, deviceId) {
|
||||||
const commissions = configManager.getCommissions(cryptoCode, deviceId, settings.config)
|
const commissions = configManager.getCommissions(cryptoCode, deviceId, settings.config)
|
||||||
const minimumTx = BN(commissions.minimumTx)
|
const minimumTx = BN(commissions.minimumTx)
|
||||||
const cashInFee = BN(commissions.fixedFee)
|
const cashInFee = BN(commissions.fixedFee)
|
||||||
|
logger.info('FEE', cashInFee)
|
||||||
const cashInCommission = BN(commissions.cashIn)
|
const cashInCommission = BN(commissions.cashIn)
|
||||||
const cashOutCommission = _.isNumber(commissions.cashOut) ? BN(commissions.cashOut) : null
|
const cashOutCommission = _.isNumber(commissions.cashOut) ? BN(commissions.cashOut) : null
|
||||||
const cryptoRec = coinUtils.getCryptoCurrency(cryptoCode)
|
const cryptoRec = coinUtils.getCryptoCurrency(cryptoCode)
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ const ThDoubleLevel = ({ title, children, className }) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const Tr = ({ error, errorMessage, children, className, size }) => {
|
const Tr = ({ onClick, error, errorMessage, children, className, size }) => {
|
||||||
const classes = useStyles({ size })
|
const classes = useStyles({ size })
|
||||||
const cardClasses = { root: classes.cardContentRoot }
|
const cardClasses = { root: classes.cardContentRoot }
|
||||||
const classNames = {
|
const classNames = {
|
||||||
|
|
@ -88,7 +88,7 @@ const Tr = ({ error, errorMessage, children, className, size }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Card className={classnames(classNames, className)}>
|
<Card className={classnames(classNames, className)} onClick={onClick}>
|
||||||
<CardContent classes={cardClasses}>
|
<CardContent classes={cardClasses}>
|
||||||
<div className={classes.mainContent}>{children}</div>
|
<div className={classes.mainContent}>{children}</div>
|
||||||
{error && <div className={classes.errorContent}>{errorMessage}</div>}
|
{error && <div className={classes.errorContent}>{errorMessage}</div>}
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ export default {
|
||||||
'&:before': {
|
'&:before': {
|
||||||
height: 0
|
height: 0
|
||||||
},
|
},
|
||||||
margin: [[4, 0]],
|
margin: [[4, 0, 0, 0]],
|
||||||
width: '100%',
|
width: '100%',
|
||||||
boxShadow: [[0, 0, 4, 0, 'rgba(0, 0, 0, 0.08)']]
|
boxShadow: [[0, 0, 4, 0, 'rgba(0, 0, 0, 0.08)']]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -38,36 +38,49 @@ const Row = ({
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
|
||||||
|
const hasPointer = onClick || expandable
|
||||||
|
const trClasses = {
|
||||||
|
[classes.pointer]: hasPointer,
|
||||||
|
[classes.row]: true,
|
||||||
|
[classes.expanded]: expanded
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div>
|
||||||
style={onClick && { cursor: 'pointer' }}
|
<div className={classnames({ [classes.before]: expanded })}>
|
||||||
onClick={() => onClick && onClick(data)}>
|
<Tr
|
||||||
<Tr
|
className={classnames(trClasses)}
|
||||||
className={classnames(classes.row)}
|
onClick={() => {
|
||||||
error={data.error}
|
expandable && expandRow(id)
|
||||||
errorMessage={data.errorMessage}>
|
onClick && onClick(data)
|
||||||
{elements.map(({ view = it => it?.toString(), ...props }, idx) => (
|
}}
|
||||||
<Td key={idx} {...props}>
|
error={data.error}
|
||||||
{view(data)}
|
errorMessage={data.errorMessage}>
|
||||||
</Td>
|
{elements.map(({ view = it => it?.toString(), ...props }, idx) => (
|
||||||
))}
|
<Td key={idx} {...props}>
|
||||||
{expandable && (
|
{view(data)}
|
||||||
<Td width={expWidth} textAlign="center">
|
</Td>
|
||||||
<button
|
))}
|
||||||
onClick={() => expandRow(id)}
|
{expandable && (
|
||||||
className={classes.expandButton}>
|
<Td width={expWidth} textAlign="center">
|
||||||
{expanded && <ExpandOpenIcon />}
|
<button
|
||||||
{!expanded && <ExpandClosedIcon />}
|
onClick={() => expandRow(id)}
|
||||||
</button>
|
className={classes.expandButton}>
|
||||||
</Td>
|
{expanded && <ExpandOpenIcon />}
|
||||||
)}
|
{!expanded && <ExpandClosedIcon />}
|
||||||
</Tr>
|
</button>
|
||||||
{expandable && expanded && (
|
</Td>
|
||||||
<Tr className={classes.detailsRow}>
|
)}
|
||||||
<Td width={width}>
|
|
||||||
<Details it={data} />
|
|
||||||
</Td>
|
|
||||||
</Tr>
|
</Tr>
|
||||||
|
</div>
|
||||||
|
{expandable && expanded && (
|
||||||
|
<div className={classes.after}>
|
||||||
|
<Tr className={classnames({ [classes.expanded]: expanded })}>
|
||||||
|
<Td width={width}>
|
||||||
|
<Details it={data} />
|
||||||
|
</Td>
|
||||||
|
</Tr>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { zircon } from 'src/styling/variables'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
expandButton: {
|
expandButton: {
|
||||||
border: 'none',
|
border: 'none',
|
||||||
|
|
@ -8,6 +10,19 @@ export default {
|
||||||
row: {
|
row: {
|
||||||
borderRadius: 0
|
borderRadius: 0
|
||||||
},
|
},
|
||||||
|
expanded: {
|
||||||
|
border: [[2, 'solid', zircon]],
|
||||||
|
boxShadow: '0 0 8px 0 rgba(0,0,0,0.08)'
|
||||||
|
},
|
||||||
|
before: {
|
||||||
|
paddingTop: 12
|
||||||
|
},
|
||||||
|
after: {
|
||||||
|
paddingBottom: 12
|
||||||
|
},
|
||||||
|
pointer: {
|
||||||
|
cursor: 'pointer'
|
||||||
|
},
|
||||||
body: {
|
body: {
|
||||||
flex: [[1, 1, 'auto']]
|
flex: [[1, 1, 'auto']]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,7 @@ const DetailsRow = ({ it: tx, ...props }) => {
|
||||||
5
|
5
|
||||||
)
|
)
|
||||||
const commissionPercentage = Number.parseFloat(tx.commissionPercentage, 2)
|
const commissionPercentage = Number.parseFloat(tx.commissionPercentage, 2)
|
||||||
const commission =
|
const commission = fiat * commissionPercentage
|
||||||
tx.txClass === 'cashOut'
|
|
||||||
? fiat * commissionPercentage
|
|
||||||
: fiat * commissionPercentage + Number.parseFloat(tx.fee)
|
|
||||||
const customer = tx.customerIdCardData && {
|
const customer = tx.customerIdCardData && {
|
||||||
name: `${onlyFirstToUpper(
|
name: `${onlyFirstToUpper(
|
||||||
tx.customerIdCardData.firstName
|
tx.customerIdCardData.firstName
|
||||||
|
|
@ -163,6 +160,12 @@ const DetailsRow = ({ it: tx, ...props }) => {
|
||||||
100} %)`}
|
100} %)`}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{tx.txClass === 'cashIn' && (
|
||||||
|
<div className={classes.innerRow}>
|
||||||
|
<Label>Fixed fee</Label>
|
||||||
|
<div>{Number.parseFloat(tx.cashInFee)}</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classnames(classes.col, classes.col3)}>
|
<div className={classnames(classes.col, classes.col3)}>
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ const GET_TRANSACTIONS = gql`
|
||||||
machineName
|
machineName
|
||||||
deviceId
|
deviceId
|
||||||
fiat
|
fiat
|
||||||
fee
|
cashInFee
|
||||||
fiatCode
|
fiatCode
|
||||||
cryptoAtoms
|
cryptoAtoms
|
||||||
cryptoCode
|
cryptoCode
|
||||||
|
|
|
||||||
41
new-lamassu-admin/todo.md
Normal file
41
new-lamassu-admin/todo.md
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
UI:
|
||||||
|
- Large input fields wiggle on editable table edit/non-edit mode change.
|
||||||
|
- all (machines/coins/...) should be a option on some overrides
|
||||||
|
|
||||||
|
Compliance:
|
||||||
|
- Reject Address Reuse missing
|
||||||
|
|
||||||
|
CoinATMRadar:
|
||||||
|
- We now have photo, should we relay that info?
|
||||||
|
|
||||||
|
Locale:
|
||||||
|
- should we show the user wallet needs to be configured after adding in a new coin?
|
||||||
|
- check if coin is active before considering it active on other screens
|
||||||
|
|
||||||
|
Commission:
|
||||||
|
- overrides can be tighter. Hide coins already used by the same machine on another line.
|
||||||
|
|
||||||
|
Sms/email:
|
||||||
|
- There's no place to pick a third party provider anymore.
|
||||||
|
|
||||||
|
Cashout:
|
||||||
|
- I've just added a zero conf limit column. Should it be like this?
|
||||||
|
|
||||||
|
Notifications:
|
||||||
|
- cashInAlertThreshold missing, used to warn to full cashbox
|
||||||
|
|
||||||
|
Machine name:
|
||||||
|
- Previously we were grabbing that from the config, but since new admin still cant change the name i`m now grabbing it from the db. Possible issues if users change the machine name from the initial one. Investivate alternatives.
|
||||||
|
|
||||||
|
Migrate:
|
||||||
|
- Need to write config migration.
|
||||||
|
- Rewrite config validate
|
||||||
|
- remove apply defaults
|
||||||
|
|
||||||
|
Compliance:
|
||||||
|
- Currently admin only handles { type: 'volume', direction: 'both' }
|
||||||
|
- Sanctions should have more care in customers.js, currently just looking if is active as if old config
|
||||||
|
|
||||||
|
Other stuff:
|
||||||
|
- sms.js
|
||||||
|
- email.js
|
||||||
139
test/fixtures/new-settings.json
vendored
Normal file
139
test/fixtures/new-settings.json
vendored
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"triggers": [
|
||||||
|
{
|
||||||
|
"id": "ce8f240f-7235-4948-b833-4af56ccfa90f",
|
||||||
|
"cashDirection": "cash-out",
|
||||||
|
"triggerType": "volume",
|
||||||
|
"threshold": "12",
|
||||||
|
"requirement": "block"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"denominations_9682f15e40539e40d3e4050a993cf74e3e157d6d9b7866fb1ebd5206024ae68a_bottom": 12,
|
||||||
|
"denominations_9682f15e40539e40d3e4050a993cf74e3e157d6d9b7866fb1ebd5206024ae68a_top": 12,
|
||||||
|
"denominations_9682f15e40539e40d3e4050a993cf74e3e157d6d9b7866fb1ebd5206024ae68a_active": true,
|
||||||
|
"locale_country": "US",
|
||||||
|
"locale_fiatCurrency": "USD",
|
||||||
|
"locale_languages": [
|
||||||
|
"en-US"
|
||||||
|
],
|
||||||
|
"locale_cryptoCurrencies": [
|
||||||
|
"BTC"
|
||||||
|
],
|
||||||
|
"commissions_minimumTx": 12,
|
||||||
|
"commissions_fixedFee": 12,
|
||||||
|
"commissions_cashOut": 12,
|
||||||
|
"commissions_cashIn": 12,
|
||||||
|
"operatorInfo_companyNumber": "123",
|
||||||
|
"operatorInfo_website": "123",
|
||||||
|
"operatorInfo_email": "123@gmail.com",
|
||||||
|
"operatorInfo_phone": "123",
|
||||||
|
"operatorInfo_name": "123",
|
||||||
|
"operatorInfo_active": true,
|
||||||
|
"receiptPrinting": {
|
||||||
|
"active": "on",
|
||||||
|
"operatorWebsite": true,
|
||||||
|
"operatorEmail": false,
|
||||||
|
"operatorPhone": false,
|
||||||
|
"companyRegistration": false,
|
||||||
|
"machineLocation": true,
|
||||||
|
"customerNameOrPhoneNumber": true,
|
||||||
|
"exchangeRate": false,
|
||||||
|
"addressQRCode": true
|
||||||
|
},
|
||||||
|
"coinAtmRadar_active": true,
|
||||||
|
"coinAtmRadar_commissions": true,
|
||||||
|
"coinAtmRadar_supportedCryptocurrencies": true,
|
||||||
|
"coinAtmRadar_supportedFiat": true,
|
||||||
|
"coinAtmRadar_supportedBuySellDirection": true,
|
||||||
|
"coinAtmRadar_limitsAndVerification": true,
|
||||||
|
"termsConditions_active": true,
|
||||||
|
"termsConditions_title": "Rasdkl",
|
||||||
|
"termsConditions_text": "123oh12",
|
||||||
|
"termsConditions_acceptButtonText": "op1i2jh3po",
|
||||||
|
"termsConditions_cancelButtonText": "12341",
|
||||||
|
"wallets_BTC_active": true,
|
||||||
|
"wallets_BTC_ticker": "mock-ticker",
|
||||||
|
"wallets_BTC_wallet": "mock-wallet",
|
||||||
|
"wallets_BTC_exchange": "mock-exchange",
|
||||||
|
"wallets_BTC_zeroConf": "mock-zero-conf",
|
||||||
|
"commissions_overrides": [
|
||||||
|
{
|
||||||
|
"minimumTx": 33,
|
||||||
|
"fixedFee": 33,
|
||||||
|
"cashOut": 33,
|
||||||
|
"cashIn": 33,
|
||||||
|
"cryptoCurrencies": [
|
||||||
|
"BTC"
|
||||||
|
],
|
||||||
|
"machine": "9682f15e40539e40d3e4050a993cf74e3e157d6d9b7866fb1ebd5206024ae68a",
|
||||||
|
"id": "423a32a9-0bbb-4997-b15a-c6db12334195",
|
||||||
|
"country": "",
|
||||||
|
"languages": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cashOut_9682f15e40539e40d3e4050a993cf74e3e157d6d9b7866fb1ebd5206024ae68a_bottom": 33,
|
||||||
|
"cashOut_9682f15e40539e40d3e4050a993cf74e3e157d6d9b7866fb1ebd5206024ae68a_top": 12,
|
||||||
|
"cashOut_9682f15e40539e40d3e4050a993cf74e3e157d6d9b7866fb1ebd5206024ae68a_active": true,
|
||||||
|
"notifications_email_active": true,
|
||||||
|
"notifications_sms_active": true,
|
||||||
|
"notifications_sms_transactions": true,
|
||||||
|
"notifications_email_compliance": true,
|
||||||
|
"notifications_highValueTransaction": 12,
|
||||||
|
"notifications_fiatBalanceCassette2": 42,
|
||||||
|
"notifications_fiatBalanceCassette1": 32,
|
||||||
|
"notifications_fiatBalanceOverrides": [
|
||||||
|
{
|
||||||
|
"cassette2": 67,
|
||||||
|
"cassette1": 556,
|
||||||
|
"machine": "9682f15e40539e40d3e4050a993cf74e3e157d6d9b7866fb1ebd5206024ae68a",
|
||||||
|
"id": "18114e5b-e6e6-4e0e-a7bc-2cc4ad605d12"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"notifications_cryptoLowBalance": 23,
|
||||||
|
"notifications_cryptoHighBalance": 56,
|
||||||
|
"notifications_cryptoBalanceOverrides": [
|
||||||
|
{
|
||||||
|
"highBalance": 66,
|
||||||
|
"lowBalance": 545,
|
||||||
|
"cryptoCurrency": "ETH",
|
||||||
|
"id": "b59e4310-bca1-435c-a89e-b861a7de9b93"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"highBalance": 23,
|
||||||
|
"lowBalance": 51,
|
||||||
|
"cryptoCurrency": "DASH",
|
||||||
|
"id": "a1f5ac7a-4b05-4ec7-8744-4d77c0555f5b"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"locale_overrides": [
|
||||||
|
{
|
||||||
|
"id": "f0f9248d-96da-4db5-b592-625251da0203",
|
||||||
|
"machine": "9682f15e40539e40d3e4050a993cf74e3e157d6d9b7866fb1ebd5206024ae68a",
|
||||||
|
"country": "US",
|
||||||
|
"languages": [
|
||||||
|
"en-CA"
|
||||||
|
],
|
||||||
|
"cryptoCurrencies": [
|
||||||
|
"ETH"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"receipt_active": "on",
|
||||||
|
"receipt_operatorWebsite": false,
|
||||||
|
"receipt_operatorEmail": false,
|
||||||
|
"receipt_operatorPhone": false,
|
||||||
|
"receipt_companyRegistration": true,
|
||||||
|
"receipt_machineLocation": false,
|
||||||
|
"receipt_customerNameOrPhoneNumber": true,
|
||||||
|
"receipt_exchangeRate": false,
|
||||||
|
"receipt_addressQRCode": false,
|
||||||
|
"notifications_sms_balance": true,
|
||||||
|
"notifications_sms_compliance": true,
|
||||||
|
"notifications_sms_errors": true,
|
||||||
|
"notifications_email_errors": true,
|
||||||
|
"notifications_email_transactions": true,
|
||||||
|
"notifications_email_balance": true
|
||||||
|
},
|
||||||
|
"accounts": {}
|
||||||
|
}
|
||||||
17
test/unit/new-settings-loader.js
Normal file
17
test/unit/new-settings-loader.js
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import test from 'ava'
|
||||||
|
import _ from 'lodash/fp'
|
||||||
|
import settings from '../../db.json'
|
||||||
|
|
||||||
|
import configManager from '../../lib/new-config-manager'
|
||||||
|
|
||||||
|
const machineId = '9682f15e40539e40d3e4050a993cf74e3e157d6d9b7866fb1ebd5206024ae68a'
|
||||||
|
const config = settings.config
|
||||||
|
|
||||||
|
test('first examples', () => {
|
||||||
|
const triggers = configManager.getTriggers(config)
|
||||||
|
const filtered = _.filter(_.matches({ triggerType: 'volume', cashDirection: 'both' }))(triggers)
|
||||||
|
const grouped = _.groupBy(_.prop('requirement'))(filtered)
|
||||||
|
const final = _.mapValues(_.compose(_.get('threshold'), _.minBy('threshold')))(grouped)
|
||||||
|
|
||||||
|
console.log(final)
|
||||||
|
})
|
||||||
Loading…
Add table
Add a link
Reference in a new issue