From d349a46f5d09157736de553f36f6ef2712e9a429 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 31 Mar 2022 12:08:09 +0200 Subject: [PATCH 01/10] Balance Resolver: calculate Decay on full sum, not including the links --- backend/src/graphql/resolver/BalanceResolver.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index 672e07b12..f5a9f6371 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -59,14 +59,17 @@ export class BalanceResolver { ? { sumHoldAvailableAmount: context.sumHoldAvailableAmount } : await transactionLinkRepository.summary(user.id, now) + // The decay is always calculated on the last booked transaction const calculatedDecay = calculateDecay( - lastTransaction.balance.minus(sumHoldAvailableAmount.toString()), + lastTransaction.balance, lastTransaction.balanceDate, now, ) 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 lastBookedBalance: lastTransaction.balance.toDecimalPlaces(2, Decimal.ROUND_DOWN), balanceGDT, From 592e16e2602cb077aa0313178d8b8fbcb0cc0bef Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 31 Mar 2022 12:09:00 +0200 Subject: [PATCH 02/10] virtual decay transaction is based on full sum not including the link values --- backend/src/graphql/resolver/TransactionResolver.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 461a70a00..14d44dc2e 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -198,13 +198,10 @@ export class TransactionResolver { // decay & link transactions 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( - virtualDecayTransaction( - lastTransaction.balance.minus(sumHoldAvailableAmount.toString()), - lastTransaction.balanceDate, - now, - self, - ), + virtualDecayTransaction(lastTransaction.balance, lastTransaction.balanceDate, now, self), ) // virtual transaction for pending transaction-links sum if (sumHoldAvailableAmount.greaterThan(0)) { From 9ed00edc52f6c4c1be4197bf9883543ddff19b24 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 31 Mar 2022 12:14:38 +0200 Subject: [PATCH 03/10] code order & comment --- backend/src/graphql/resolver/BalanceResolver.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index f5a9f6371..f30e779e5 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -54,11 +54,6 @@ export class BalanceResolver { }, }) - const transactionLinkRepository = getCustomRepository(TransactionLinkRepository) - const { sumHoldAvailableAmount } = context.sumHoldAvailableAmount - ? { sumHoldAvailableAmount: context.sumHoldAvailableAmount } - : await transactionLinkRepository.summary(user.id, now) - // The decay is always calculated on the last booked transaction const calculatedDecay = calculateDecay( lastTransaction.balance, @@ -66,6 +61,12 @@ export class BalanceResolver { now, ) + // The final balance is reduced by the link amount withheld + const transactionLinkRepository = getCustomRepository(TransactionLinkRepository) + const { sumHoldAvailableAmount } = context.sumHoldAvailableAmount + ? { sumHoldAvailableAmount: context.sumHoldAvailableAmount } + : await transactionLinkRepository.summary(user.id, now) + return new Balance({ balance: calculatedDecay.balance .minus(sumHoldAvailableAmount.toString()) From a9ba92f67bb207bd8ba744861c0ef64add4918b2 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 31 Mar 2022 12:32:35 +0200 Subject: [PATCH 04/10] Transaction Resolver: transmit Redeem Link to calculateBalance --- backend/src/graphql/resolver/TransactionResolver.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 461a70a00..240369006 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -57,7 +57,12 @@ export const executeTransaction = async ( // validate amount 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) { throw new Error("user hasn't enough GDD or amount is < 0") } From fa7f2b9d87581f7c07dee6c64b8a01e3697de355 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 31 Mar 2022 12:33:29 +0200 Subject: [PATCH 05/10] calculateBalance: If we redeem a link, make sure we do not consider its amount as blocked when calculating the balance --- backend/src/util/validate.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/backend/src/util/validate.ts b/backend/src/util/validate.ts index 95e1bf699..5d2f39aa0 100644 --- a/backend/src/util/validate.ts +++ b/backend/src/util/validate.ts @@ -4,6 +4,7 @@ import { Transaction } from '@entity/Transaction' import { Decay } from '@model/Decay' import { getCustomRepository } from '@dbTools/typeorm' import { TransactionLinkRepository } from '@repository/TransactionLink' +import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink' function isStringBoolean(value: string): boolean { const lowerValue = value.toLowerCase() @@ -21,6 +22,7 @@ async function calculateBalance( userId: number, amount: Decimal, time: Date, + transactionLink?: dbTransactionLink | null, ): Promise<{ balance: Decimal; decay: Decay; lastTransactionId: number } | null> { const lastTransaction = await Transaction.findOne({ userId }, { order: { balanceDate: 'DESC' } }) if (!lastTransaction) return null @@ -32,7 +34,13 @@ async function calculateBalance( const transactionLinkRepository = getCustomRepository(TransactionLinkRepository) 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 calculated as blocked + // else we cannot redeem links which are more or equal to half of what an account actually owns + const sumHoldAvailableAmountMinusTransactionLink = transactionLink + ? sumHoldAvailableAmount.minus(transactionLink.amount.toString()) + : sumHoldAvailableAmount + + if (balance.minus(sumHoldAvailableAmountMinusTransactionLink.toString()).lessThan(0)) { return null } return { balance, lastTransactionId: lastTransaction.id, decay } From 04807bd225603f6c88c60052e51bb90cf24c4e93 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 31 Mar 2022 12:34:09 +0200 Subject: [PATCH 06/10] corrected comment --- backend/src/util/validate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/util/validate.ts b/backend/src/util/validate.ts index 5d2f39aa0..1a0ce02ce 100644 --- a/backend/src/util/validate.ts +++ b/backend/src/util/validate.ts @@ -34,7 +34,7 @@ async function calculateBalance( const transactionLinkRepository = getCustomRepository(TransactionLinkRepository) const { sumHoldAvailableAmount } = await transactionLinkRepository.summary(userId, time) - // If we want to redeem a link we need to make sure that the link amount is not calculated as blocked + // 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 sumHoldAvailableAmountMinusTransactionLink = transactionLink ? sumHoldAvailableAmount.minus(transactionLink.amount.toString()) From b53aef90f883a06ff789e652ef68f1f846e02f23 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 31 Mar 2022 20:52:59 +0200 Subject: [PATCH 07/10] Update backend/src/util/validate.ts Co-authored-by: Moriz Wahl --- backend/src/util/validate.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/backend/src/util/validate.ts b/backend/src/util/validate.ts index 1a0ce02ce..b158761da 100644 --- a/backend/src/util/validate.ts +++ b/backend/src/util/validate.ts @@ -36,11 +36,9 @@ async function calculateBalance( // 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 sumHoldAvailableAmountMinusTransactionLink = transactionLink - ? sumHoldAvailableAmount.minus(transactionLink.amount.toString()) - : sumHoldAvailableAmount + const releasedLinkAmount = transactionLink ? transactionLink.amount : new Decimal(0) - if (balance.minus(sumHoldAvailableAmountMinusTransactionLink.toString()).lessThan(0)) { + if (balance.minus(sumHoldAvailableAmount.toString()).plus(releasedLinkAmount.toString()).lessThan(0)) { return null } return { balance, lastTransactionId: lastTransaction.id, decay } From ef675980a8fc0266c2aecb97f3068ed636b34ad6 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 31 Mar 2022 21:04:16 +0200 Subject: [PATCH 08/10] lint fixes --- backend/src/util/validate.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/util/validate.ts b/backend/src/util/validate.ts index b158761da..3c8cd5935 100644 --- a/backend/src/util/validate.ts +++ b/backend/src/util/validate.ts @@ -38,7 +38,9 @@ async function calculateBalance( // else we cannot redeem links which are more or equal to half of what an account actually owns const releasedLinkAmount = transactionLink ? transactionLink.amount : new Decimal(0) - if (balance.minus(sumHoldAvailableAmount.toString()).plus(releasedLinkAmount.toString()).lessThan(0)) { + if ( + balance.minus(sumHoldAvailableAmount.toString()).plus(releasedLinkAmount.toString()).lessThan(0) + ) { return null } return { balance, lastTransactionId: lastTransaction.id, decay } From 3ef0074d33f657979e68806f9a73ac9259e19d98 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 31 Mar 2022 21:47:55 +0200 Subject: [PATCH 09/10] free not only the link value but also the decay amount withheld --- backend/src/util/validate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/util/validate.ts b/backend/src/util/validate.ts index 3c8cd5935..8d1c90ca4 100644 --- a/backend/src/util/validate.ts +++ b/backend/src/util/validate.ts @@ -36,7 +36,7 @@ async function calculateBalance( // 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.amount : new Decimal(0) + const releasedLinkAmount = transactionLink ? transactionLink.holdAvailableAmount : new Decimal(0) if ( balance.minus(sumHoldAvailableAmount.toString()).plus(releasedLinkAmount.toString()).lessThan(0) From 681d34b1dc7e36076d570d647e44d68f6742137e Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 31 Mar 2022 22:17:36 +0200 Subject: [PATCH 10/10] rounding in virtual decay transaction, pass hold available amount to virtual decay creation --- backend/src/graphql/resolver/TransactionResolver.ts | 8 +++++++- backend/src/util/virtualTransactions.ts | 9 ++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 14d44dc2e..c86154583 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -201,7 +201,13 @@ export class TransactionResolver { // 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( - virtualDecayTransaction(lastTransaction.balance, lastTransaction.balanceDate, now, self), + virtualDecayTransaction( + lastTransaction.balance, + lastTransaction.balanceDate, + now, + self, + sumHoldAvailableAmount, + ), ) // virtual transaction for pending transaction-links sum if (sumHoldAvailableAmount.greaterThan(0)) { diff --git a/backend/src/util/virtualTransactions.ts b/backend/src/util/virtualTransactions.ts index e4b9eec1f..ff1b7548e 100644 --- a/backend/src/util/virtualTransactions.ts +++ b/backend/src/util/virtualTransactions.ts @@ -59,6 +59,7 @@ const virtualDecayTransaction = ( balanceDate: Date, time: Date = new Date(), user: User, + holdAvailabeAmount: Decimal, ): Transaction => { const decay = calculateDecay(balance, balanceDate, time) // const balance = decay.balance.minus(lastTransaction.balance) @@ -67,10 +68,12 @@ const virtualDecayTransaction = ( userId: -1, previous: -1, typeId: TransactionTypeId.DECAY, - amount: decay.decay ? decay.decay : new Decimal(0), // new Decimal(0), // this kinda is wrong, but helps with the frontend query - balance: decay.balance, + 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 + .minus(holdAvailabeAmount.toString()) + .toDecimalPlaces(2, Decimal.ROUND_DOWN), 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, memo: '', creationDate: null,