feat: show transaction sweep status

This commit is contained in:
Sérgio Salgado 2022-07-28 03:44:19 +01:00
parent fa0ef6b053
commit 10245bbb19
8 changed files with 61 additions and 19 deletions

View file

@ -21,7 +21,8 @@ function transaction () {
SELECT 'address' AS type, to_address AS value FROM cash_in_txs UNION SELECT 'address' AS type, to_address AS value FROM cash_in_txs UNION
SELECT 'address' AS type, to_address AS value FROM cash_out_txs UNION SELECT 'address' AS type, to_address AS value FROM cash_out_txs UNION
SELECT 'status' AS type, ${cashInTx.TRANSACTION_STATES} AS value FROM cash_in_txs UNION SELECT 'status' AS type, ${cashInTx.TRANSACTION_STATES} AS value FROM cash_in_txs UNION
SELECT 'status' AS type, ${CASH_OUT_TRANSACTION_STATES} AS value FROM cash_out_txs SELECT 'status' AS type, ${CASH_OUT_TRANSACTION_STATES} AS value FROM cash_out_txs UNION
SELECT 'sweep status' AS type, CASE WHEN swept THEN 'Swept' WHEN NOT swept THEN 'Unswept' END AS value FROM cash_out_txs
) f` ) f`
return db.any(sql) return db.any(sql)

View file

@ -19,11 +19,11 @@ const resolvers = {
isAnonymous: parent => (parent.customerId === anonymous.uuid) isAnonymous: parent => (parent.customerId === anonymous.uuid)
}, },
Query: { Query: {
transactions: (...[, { from, until, limit, offset, deviceId, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status, excludeTestingCustomers }]) => transactions: (...[, { from, until, limit, offset, deviceId, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status, swept, excludeTestingCustomers }]) =>
transactions.batch(from, until, limit, offset, deviceId, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status, excludeTestingCustomers), transactions.batch(from, until, limit, offset, deviceId, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status, swept, excludeTestingCustomers),
transactionsCsv: (...[, { from, until, limit, offset, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status, timezone, excludeTestingCustomers, simplified }]) => transactionsCsv: (...[, { from, until, limit, offset, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status, swept, timezone, excludeTestingCustomers, simplified }]) =>
transactions.batch(from, until, limit, offset, null, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status, excludeTestingCustomers, simplified) transactions.batch(from, until, limit, offset, null, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status, swept, excludeTestingCustomers, simplified)
.then(data => parseAsync(logDateFormat(timezone, data, ['created', 'sendTime']))), .then(data => parseAsync(logDateFormat(timezone, data, ['created', 'sendTime', 'publishedAt']))),
transactionCsv: (...[, { id, txClass, timezone }]) => transactionCsv: (...[, { id, txClass, timezone }]) =>
transactions.getTx(id, txClass).then(data => transactions.getTx(id, txClass).then(data =>
parseAsync(logDateFormat(timezone, [data], ['created', 'sendTime'])) parseAsync(logDateFormat(timezone, [data], ['created', 'sendTime']))

View file

@ -50,6 +50,7 @@ const typeDef = gql`
batchError: String batchError: String
walletScore: Int walletScore: Int
profit: String profit: String
swept: Boolean
} }
type Filter { type Filter {
@ -58,8 +59,8 @@ const typeDef = gql`
} }
type Query { type Query {
transactions(from: Date, until: Date, limit: Int, offset: Int, deviceId: ID, txClass: String, machineName: String, customerName: String, fiatCode: String, cryptoCode: String, toAddress: String, status: String, excludeTestingCustomers: Boolean): [Transaction] @auth transactions(from: Date, until: Date, limit: Int, offset: Int, deviceId: ID, txClass: String, machineName: String, customerName: String, fiatCode: String, cryptoCode: String, toAddress: String, status: String, swept: Boolean, excludeTestingCustomers: Boolean): [Transaction] @auth
transactionsCsv(from: Date, until: Date, limit: Int, offset: Int, txClass: String, machineName: String, customerName: String, fiatCode: String, cryptoCode: String, toAddress: String, status: String, timezone: String, excludeTestingCustomers: Boolean, simplified: Boolean): String @auth transactionsCsv(from: Date, until: Date, limit: Int, offset: Int, txClass: String, machineName: String, customerName: String, fiatCode: String, cryptoCode: String, toAddress: String, status: String, swept: Boolean, timezone: String, excludeTestingCustomers: Boolean, simplified: Boolean): String @auth
transactionCsv(id: ID, txClass: String, timezone: String): String @auth transactionCsv(id: ID, txClass: String, timezone: String): String @auth
txAssociatedDataCsv(id: ID, txClass: String, timezone: String): String @auth txAssociatedDataCsv(id: ID, txClass: String, timezone: String): String @auth
transactionFilters: [Filter] @auth transactionFilters: [Filter] @auth

View file

@ -46,6 +46,7 @@ function batch (
cryptoCode = null, cryptoCode = null,
toAddress = null, toAddress = null,
status = null, status = null,
swept = null,
excludeTestingCustomers = false, excludeTestingCustomers = false,
simplified simplified
) { ) {
@ -109,14 +110,33 @@ function batch (
AND ($11 is null or txs.crypto_code = $11) AND ($11 is null or txs.crypto_code = $11)
AND ($12 is null or txs.to_address = $12) AND ($12 is null or txs.to_address = $12)
AND ($13 is null or txs.txStatus = $13) AND ($13 is null or txs.txStatus = $13)
AND ($14 is null or txs.swept = $14)
${excludeTestingCustomers ? `AND c.is_test_customer is false` : ``} ${excludeTestingCustomers ? `AND c.is_test_customer is false` : ``}
AND (fiat > 0) AND (fiat > 0)
ORDER BY created DESC limit $4 offset $5` ORDER BY created DESC limit $4 offset $5`
return Promise.all([ // The swept filter is cash-out only, so omit the cash-in query entirely
const hasCashInOnlyFilters = false
const hasCashOutOnlyFilters = !_.isNil(swept)
let promises
if (hasCashInOnlyFilters && hasCashOutOnlyFilters) {
throw new Error('Trying to filter transactions with mutually exclusive filters')
}
if (hasCashInOnlyFilters) {
promises = [db.any(cashInSql, [cashInTx.PENDING_INTERVAL, from, until, limit, offset, id, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status])]
} else if (hasCashOutOnlyFilters) {
promises = [db.any(cashOutSql, [REDEEMABLE_AGE, from, until, limit, offset, id, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status, swept])]
} else {
promises = [
db.any(cashInSql, [cashInTx.PENDING_INTERVAL, from, until, limit, offset, id, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status]), db.any(cashInSql, [cashInTx.PENDING_INTERVAL, from, until, limit, offset, id, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status]),
db.any(cashOutSql, [REDEEMABLE_AGE, from, until, limit, offset, id, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status]) db.any(cashOutSql, [REDEEMABLE_AGE, from, until, limit, offset, id, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status, swept])
]) ]
}
return Promise.all(promises)
.then(packager) .then(packager)
.then(res => { .then(res => {
if (simplified) return simplifiedBatch(res) if (simplified) return simplifiedBatch(res)

View file

@ -7,7 +7,7 @@ import { P, Label3 } from 'src/components/typography'
import { ReactComponent as CloseIcon } from 'src/styling/icons/action/close/zodiac.svg' import { ReactComponent as CloseIcon } from 'src/styling/icons/action/close/zodiac.svg'
import { ReactComponent as FilterIcon } from 'src/styling/icons/button/filter/white.svg' import { ReactComponent as FilterIcon } from 'src/styling/icons/button/filter/white.svg'
import { ReactComponent as ReverseFilterIcon } from 'src/styling/icons/button/filter/zodiac.svg' import { ReactComponent as ReverseFilterIcon } from 'src/styling/icons/button/filter/zodiac.svg'
import { onlyFirstToUpper } from 'src/utils/string' import { onlyFirstToUpper, singularOrPlural } from 'src/utils/string'
import { chipStyles, styles } from './SearchFilter.styles' import { chipStyles, styles } from './SearchFilter.styles'
@ -18,7 +18,7 @@ const SearchFilter = ({
filters, filters,
onFilterDelete, onFilterDelete,
deleteAllFilters, deleteAllFilters,
entries entries = 0
}) => { }) => {
const chipClasses = useChipStyles() const chipClasses = useChipStyles()
const classes = useStyles() const classes = useStyles()
@ -40,8 +40,11 @@ const SearchFilter = ({
</div> </div>
<div className={classes.deleteWrapper}> <div className={classes.deleteWrapper}>
{ {
<Label3 className={classes.entries}>{`${entries ?? <Label3 className={classes.entries}>{`${entries} ${singularOrPlural(
0} entries`}</Label3> entries,
`entry`,
`entries`
)}`}</Label3>
} }
<ActionButton <ActionButton
color="secondary" color="secondary"

View file

@ -405,6 +405,14 @@ const DetailsRow = ({ it: tx, timezone }) => {
</ActionButton> </ActionButton>
)} )}
</div> </div>
{!R.isNil(tx.swept) && (
<div className={classes.swept}>
<Label>Sweep status</Label>
<span className={classes.bold}>
{tx.swept ? `Swept` : `Unswept`}
</span>
</div>
)}
<div> <div>
<Label>Other actions</Label> <Label>Other actions</Label>
<div className={classes.otherActionsGroup}> <div className={classes.otherActionsGroup}>

View file

@ -131,5 +131,8 @@ export default {
}, },
error: { error: {
color: tomato color: tomato
},
swept: {
width: 250
} }
} }

View file

@ -75,6 +75,7 @@ const GET_TRANSACTIONS = gql`
$cryptoCode: String $cryptoCode: String
$toAddress: String $toAddress: String
$status: String $status: String
$swept: Boolean
) { ) {
transactions( transactions(
limit: $limit limit: $limit
@ -87,6 +88,7 @@ const GET_TRANSACTIONS = gql`
cryptoCode: $cryptoCode cryptoCode: $cryptoCode
toAddress: $toAddress toAddress: $toAddress
status: $status status: $status
swept: $swept
) { ) {
id id
txClass txClass
@ -121,6 +123,7 @@ const GET_TRANSACTIONS = gql`
rawTickerPrice rawTickerPrice
batchError batchError
walletScore walletScore
swept
} }
} }
` `
@ -246,7 +249,8 @@ const Transactions = () => {
fiatCode: filtersObject.fiat, fiatCode: filtersObject.fiat,
cryptoCode: filtersObject.crypto, cryptoCode: filtersObject.crypto,
toAddress: filtersObject.address, toAddress: filtersObject.address,
status: filtersObject.status status: filtersObject.status,
swept: filtersObject.swept === 'Swept'
}) })
refetch && refetch() refetch && refetch()
@ -269,7 +273,8 @@ const Transactions = () => {
fiatCode: filtersObject.fiat, fiatCode: filtersObject.fiat,
cryptoCode: filtersObject.crypto, cryptoCode: filtersObject.crypto,
toAddress: filtersObject.address, toAddress: filtersObject.address,
status: filtersObject.status status: filtersObject.status,
swept: filtersObject.swept === 'Swept'
}) })
refetch && refetch() refetch && refetch()
@ -287,7 +292,8 @@ const Transactions = () => {
fiatCode: filtersObject.fiat, fiatCode: filtersObject.fiat,
cryptoCode: filtersObject.crypto, cryptoCode: filtersObject.crypto,
toAddress: filtersObject.address, toAddress: filtersObject.address,
status: filtersObject.status status: filtersObject.status,
swept: filtersObject.swept === 'Swept'
}) })
refetch && refetch() refetch && refetch()