Merge branch 'master' into 1686-When-sending-takes-longer-no-twice-results

This commit is contained in:
Alexander Friedland 2022-03-31 23:03:36 +02:00 committed by GitHub
commit ecf6721c1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 13 deletions

View File

@ -54,19 +54,23 @@ export class BalanceResolver {
}, },
}) })
// The decay is always calculated on the last booked transaction
const calculatedDecay = calculateDecay(
lastTransaction.balance,
lastTransaction.balanceDate,
now,
)
// The final balance is reduced by the link amount withheld
const transactionLinkRepository = getCustomRepository(TransactionLinkRepository) const transactionLinkRepository = getCustomRepository(TransactionLinkRepository)
const { sumHoldAvailableAmount } = context.sumHoldAvailableAmount const { sumHoldAvailableAmount } = context.sumHoldAvailableAmount
? { sumHoldAvailableAmount: context.sumHoldAvailableAmount } ? { sumHoldAvailableAmount: context.sumHoldAvailableAmount }
: await transactionLinkRepository.summary(user.id, now) : await transactionLinkRepository.summary(user.id, now)
const calculatedDecay = calculateDecay(
lastTransaction.balance.minus(sumHoldAvailableAmount.toString()),
lastTransaction.balanceDate,
now,
)
return new Balance({ return new Balance({
balance: calculatedDecay.balance.toDecimalPlaces(2, Decimal.ROUND_DOWN), // round towards zero balance: calculatedDecay.balance
.minus(sumHoldAvailableAmount.toString())
.toDecimalPlaces(2, Decimal.ROUND_DOWN), // round towards zero
decay: calculatedDecay.decay.toDecimalPlaces(2, Decimal.ROUND_FLOOR), // round towards - infinity decay: calculatedDecay.decay.toDecimalPlaces(2, Decimal.ROUND_FLOOR), // round towards - infinity
lastBookedBalance: lastTransaction.balance.toDecimalPlaces(2, Decimal.ROUND_DOWN), lastBookedBalance: lastTransaction.balance.toDecimalPlaces(2, Decimal.ROUND_DOWN),
balanceGDT, balanceGDT,

View File

@ -57,7 +57,12 @@ export const executeTransaction = async (
// validate amount // validate amount
const receivedCallDate = new Date() const receivedCallDate = new Date()
const sendBalance = await calculateBalance(sender.id, amount.mul(-1), receivedCallDate) const sendBalance = await calculateBalance(
sender.id,
amount.mul(-1),
receivedCallDate,
transactionLink,
)
if (!sendBalance) { if (!sendBalance) {
throw new Error("user hasn't enough GDD or amount is < 0") throw new Error("user hasn't enough GDD or amount is < 0")
} }
@ -198,12 +203,15 @@ export class TransactionResolver {
// decay & link transactions // decay & link transactions
if (currentPage === 1 && order === Order.DESC) { if (currentPage === 1 && order === Order.DESC) {
// The virtual decay is always on the booked amount, not including the generated, not yet booked links,
// since the decay is substantially different when the amount is less
transactions.push( transactions.push(
virtualDecayTransaction( virtualDecayTransaction(
lastTransaction.balance.minus(sumHoldAvailableAmount.toString()), lastTransaction.balance,
lastTransaction.balanceDate, lastTransaction.balanceDate,
now, now,
self, self,
sumHoldAvailableAmount,
), ),
) )
// virtual transaction for pending transaction-links sum // virtual transaction for pending transaction-links sum

View File

@ -4,6 +4,7 @@ import { Transaction } from '@entity/Transaction'
import { Decay } from '@model/Decay' import { Decay } from '@model/Decay'
import { getCustomRepository } from '@dbTools/typeorm' import { getCustomRepository } from '@dbTools/typeorm'
import { TransactionLinkRepository } from '@repository/TransactionLink' import { TransactionLinkRepository } from '@repository/TransactionLink'
import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink'
function isStringBoolean(value: string): boolean { function isStringBoolean(value: string): boolean {
const lowerValue = value.toLowerCase() const lowerValue = value.toLowerCase()
@ -21,6 +22,7 @@ async function calculateBalance(
userId: number, userId: number,
amount: Decimal, amount: Decimal,
time: Date, time: Date,
transactionLink?: dbTransactionLink | null,
): Promise<{ balance: Decimal; decay: Decay; lastTransactionId: number } | null> { ): Promise<{ balance: Decimal; decay: Decay; lastTransactionId: number } | null> {
const lastTransaction = await Transaction.findOne({ userId }, { order: { balanceDate: 'DESC' } }) const lastTransaction = await Transaction.findOne({ userId }, { order: { balanceDate: 'DESC' } })
if (!lastTransaction) return null if (!lastTransaction) return null
@ -32,7 +34,13 @@ async function calculateBalance(
const transactionLinkRepository = getCustomRepository(TransactionLinkRepository) const transactionLinkRepository = getCustomRepository(TransactionLinkRepository)
const { sumHoldAvailableAmount } = await transactionLinkRepository.summary(userId, time) const { sumHoldAvailableAmount } = await transactionLinkRepository.summary(userId, time)
if (balance.minus(sumHoldAvailableAmount.toString()).lessThan(0)) { // If we want to redeem a link we need to make sure that the link amount is not considered as blocked
// else we cannot redeem links which are more or equal to half of what an account actually owns
const releasedLinkAmount = transactionLink ? transactionLink.holdAvailableAmount : new Decimal(0)
if (
balance.minus(sumHoldAvailableAmount.toString()).plus(releasedLinkAmount.toString()).lessThan(0)
) {
return null return null
} }
return { balance, lastTransactionId: lastTransaction.id, decay } return { balance, lastTransactionId: lastTransaction.id, decay }

View File

@ -59,6 +59,7 @@ const virtualDecayTransaction = (
balanceDate: Date, balanceDate: Date,
time: Date = new Date(), time: Date = new Date(),
user: User, user: User,
holdAvailabeAmount: Decimal,
): Transaction => { ): Transaction => {
const decay = calculateDecay(balance, balanceDate, time) const decay = calculateDecay(balance, balanceDate, time)
// const balance = decay.balance.minus(lastTransaction.balance) // const balance = decay.balance.minus(lastTransaction.balance)
@ -67,10 +68,12 @@ const virtualDecayTransaction = (
userId: -1, userId: -1,
previous: -1, previous: -1,
typeId: TransactionTypeId.DECAY, typeId: TransactionTypeId.DECAY,
amount: decay.decay ? decay.decay : new Decimal(0), // new Decimal(0), // this kinda is wrong, but helps with the frontend query amount: decay.decay ? decay.decay.toDecimalPlaces(2, Decimal.ROUND_FLOOR) : new Decimal(0), // new Decimal(0), // this kinda is wrong, but helps with the frontend query
balance: decay.balance, balance: decay.balance
.minus(holdAvailabeAmount.toString())
.toDecimalPlaces(2, Decimal.ROUND_DOWN),
balanceDate: time, balanceDate: time,
decay: decay.decay ? decay.decay : new Decimal(0), decay: decay.decay ? decay.decay.toDecimalPlaces(2, Decimal.ROUND_FLOOR) : new Decimal(0),
decayStart: decay.start, decayStart: decay.start,
memo: '', memo: '',
creationDate: null, creationDate: null,