252 lines
6 KiB
JavaScript
252 lines
6 KiB
JavaScript
const _ = require('lodash/fp')
|
|
|
|
const db = require('../../db')
|
|
const BN = require('../../bn')
|
|
const { utils: coinUtils } = require('@lamassu/coins')
|
|
const cashInTx = require('../../cash-in/cash-in-tx')
|
|
const { REDEEMABLE_AGE } = require('../../cash-out/cash-out-helper')
|
|
const {
|
|
transactions: { getTransactionList },
|
|
} = require('typesafe-db')
|
|
|
|
function addProfits(txs) {
|
|
return _.map(
|
|
it => ({
|
|
...it,
|
|
profit: getProfit(it).toString(),
|
|
cryptoAmount: getCryptoAmount(it).toString(),
|
|
}),
|
|
txs,
|
|
)
|
|
}
|
|
|
|
function batch({
|
|
from = new Date(0).toISOString(),
|
|
until = new Date().toISOString(),
|
|
limit = null,
|
|
offset = 0,
|
|
txClass = null,
|
|
deviceId = null,
|
|
customerId = null,
|
|
cryptoCode = null,
|
|
toAddress = null,
|
|
status = null,
|
|
swept = null,
|
|
excludeTestingCustomers = false,
|
|
simplified,
|
|
}) {
|
|
const isCsvExport = _.isBoolean(simplified)
|
|
return (
|
|
Promise.all([
|
|
getTransactionList(
|
|
{
|
|
from,
|
|
until,
|
|
cryptoCode,
|
|
txClass,
|
|
deviceId,
|
|
toAddress,
|
|
customerId,
|
|
swept,
|
|
status,
|
|
excludeTestingCustomers,
|
|
},
|
|
{ limit, offset },
|
|
),
|
|
])
|
|
// Promise.all(promises)
|
|
.then(it => addProfits(it[0]))
|
|
.then(res =>
|
|
!isCsvExport
|
|
? res
|
|
: // GQL transactions and transactionsCsv both use this function and
|
|
// if we don't check for the correct simplified value, the Transactions page polling
|
|
// will continuously build a csv in the background
|
|
simplified
|
|
? simplifiedBatch(res)
|
|
: advancedBatch(res),
|
|
)
|
|
)
|
|
}
|
|
|
|
function advancedBatch(data) {
|
|
const fields = [
|
|
'txClass',
|
|
'id',
|
|
'deviceId',
|
|
'toAddress',
|
|
'cryptoAtoms',
|
|
'cryptoCode',
|
|
'fiat',
|
|
'fiatCode',
|
|
'fee',
|
|
'status',
|
|
'profit',
|
|
'cryptoAmount',
|
|
'dispense',
|
|
'notified',
|
|
'redeem',
|
|
'phone',
|
|
'error',
|
|
'fixedFee',
|
|
'created',
|
|
'confirmedAt',
|
|
'hdIndex',
|
|
'swept',
|
|
'timedout',
|
|
'dispenseConfirmed',
|
|
'provisioned1',
|
|
'provisioned2',
|
|
'provisioned3',
|
|
'provisioned4',
|
|
'provisionedRecycler1',
|
|
'provisionedRecycler2',
|
|
'provisionedRecycler3',
|
|
'provisionedRecycler4',
|
|
'provisionedRecycler5',
|
|
'provisionedRecycler6',
|
|
'denomination1',
|
|
'denomination2',
|
|
'denomination3',
|
|
'denomination4',
|
|
'denominationRecycler1',
|
|
'denominationRecycler2',
|
|
'denominationRecycler3',
|
|
'denominationRecycler4',
|
|
'denominationRecycler5',
|
|
'denominationRecycler6',
|
|
'errorCode',
|
|
'customerId',
|
|
'txVersion',
|
|
'publishedAt',
|
|
'termsAccepted',
|
|
'layer2Address',
|
|
'commissionPercentage',
|
|
'rawTickerPrice',
|
|
'receivedCryptoAtoms',
|
|
'discount',
|
|
'txHash',
|
|
'customerPhone',
|
|
'customerEmail',
|
|
'customerIdCardDataNumber',
|
|
'customerIdCardDataExpiration',
|
|
'customerIdCardData',
|
|
'customerName',
|
|
'sendTime',
|
|
'customerFrontCameraPath',
|
|
'customerIdCardPhotoPath',
|
|
'expired',
|
|
'machineName',
|
|
'walletScore',
|
|
]
|
|
|
|
const addAdvancedFields = _.map(it => ({
|
|
...it,
|
|
fixedFee: it.fixedFee ?? null,
|
|
fee: it.fee ?? null,
|
|
}))
|
|
|
|
return _.compose(_.map(_.pick(fields)), addAdvancedFields)(data)
|
|
}
|
|
|
|
function simplifiedBatch(data) {
|
|
const fields = [
|
|
'txClass',
|
|
'id',
|
|
'created',
|
|
'machineName',
|
|
'fee',
|
|
'cryptoCode',
|
|
'cryptoAtoms',
|
|
'fiat',
|
|
'fiatCode',
|
|
'phone',
|
|
'email',
|
|
'toAddress',
|
|
'txHash',
|
|
'dispense',
|
|
'error',
|
|
'status',
|
|
'profit',
|
|
'cryptoAmount',
|
|
]
|
|
|
|
return _.map(_.pick(fields))(data)
|
|
}
|
|
|
|
const getCryptoAmount = it =>
|
|
coinUtils.toUnit(BN(it.cryptoAtoms), it.cryptoCode)
|
|
|
|
const getProfit = it => {
|
|
/* fiat - crypto*tickerPrice */
|
|
const calcCashInProfit = (fiat, crypto, tickerPrice) =>
|
|
fiat.minus(crypto.times(tickerPrice))
|
|
/* crypto*tickerPrice - fiat */
|
|
const calcCashOutProfit = (fiat, crypto, tickerPrice) =>
|
|
crypto.times(tickerPrice).minus(fiat)
|
|
|
|
const fiat = BN(it.fiat)
|
|
const crypto = getCryptoAmount(it)
|
|
const tickerPrice = BN(it.rawTickerPrice)
|
|
const isCashIn = it.txClass === 'cashIn'
|
|
|
|
return isCashIn
|
|
? calcCashInProfit(fiat, crypto, tickerPrice)
|
|
: calcCashOutProfit(fiat, crypto, tickerPrice)
|
|
}
|
|
|
|
function getTx(txId, txClass) {
|
|
const cashInSql = `select 'cashIn' as tx_class, txs.*,
|
|
((not txs.send_confirmed) and (txs.created <= now() - interval $1)) as expired
|
|
from cash_in_txs as txs
|
|
where txs.id=$2`
|
|
|
|
const cashOutSql = `select 'cashOut' as tx_class,
|
|
txs.*,
|
|
(extract(epoch from (now() - greatest(txs.created, txs.confirmed_at))) * 1000) >= $2 as expired
|
|
from cash_out_txs txs
|
|
where txs.id=$1`
|
|
|
|
return txClass === 'cashIn'
|
|
? db.oneOrNone(cashInSql, [cashInTx.PENDING_INTERVAL, txId])
|
|
: db.oneOrNone(cashOutSql, [txId, REDEEMABLE_AGE])
|
|
}
|
|
|
|
function getTxAssociatedData(txId, txClass) {
|
|
const billsSql = `select 'bills' as bills, b.* from bills b where cash_in_txs_id = $1`
|
|
const actionsSql = `select 'cash_out_actions' as cash_out_actions, actions.* from cash_out_actions actions where tx_id = $1`
|
|
|
|
return txClass === 'cashIn'
|
|
? db.manyOrNone(billsSql, [txId])
|
|
: db.manyOrNone(actionsSql, [txId])
|
|
}
|
|
|
|
function updateTxCustomerPhoto(customerId, txId, direction, data) {
|
|
const formattedData = _.mapKeys(_.snakeCase, data)
|
|
const cashInSql =
|
|
'UPDATE cash_in_txs SET tx_customer_photo_at = $1, tx_customer_photo_path = $2 WHERE customer_id=$3 AND id=$4'
|
|
|
|
const cashOutSql =
|
|
'UPDATE cash_out_txs SET tx_customer_photo_at = $1, tx_customer_photo_path = $2 WHERE customer_id=$3 AND id=$4'
|
|
|
|
return direction === 'cashIn'
|
|
? db.oneOrNone(cashInSql, [
|
|
formattedData.tx_customer_photo_at,
|
|
formattedData.tx_customer_photo_path,
|
|
customerId,
|
|
txId,
|
|
])
|
|
: db.oneOrNone(cashOutSql, [
|
|
formattedData.tx_customer_photo_at,
|
|
formattedData.tx_customer_photo_path,
|
|
customerId,
|
|
txId,
|
|
])
|
|
}
|
|
|
|
module.exports = {
|
|
batch,
|
|
getTx,
|
|
getTxAssociatedData,
|
|
updateTxCustomerPhoto,
|
|
}
|