mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
made decay block static
removed duplicate implementation of decay calculation
This commit is contained in:
parent
302b5ad75b
commit
378bae4323
@ -5,6 +5,7 @@ dotenv.config()
|
||||
|
||||
const constants = {
|
||||
DB_VERSION: '0016-transaction_signatures',
|
||||
DECAY_START_TIME: new Date('2021-05-13 17:46:31'), // GMT+0
|
||||
}
|
||||
|
||||
const server = {
|
||||
|
||||
@ -4,7 +4,7 @@ import { ObjectType, Field, Int } from 'type-graphql'
|
||||
|
||||
@ObjectType()
|
||||
export class Decay {
|
||||
constructor(json: any) {
|
||||
constructor(json?: any) {
|
||||
if (json) {
|
||||
this.balance = Number(json.balance)
|
||||
this.decayStart = json.decay_start
|
||||
|
||||
@ -29,7 +29,7 @@ import { Balance as dbBalance } from '@entity/Balance'
|
||||
|
||||
import { apiPost } from '../../apis/HttpRequest'
|
||||
import { roundFloorFrom4, roundCeilFrom4 } from '../../util/round'
|
||||
import { calculateDecay, calculateDecayWithInterval } from '../../util/decay'
|
||||
import { calculateDecay } from '../../util/decay'
|
||||
import { TransactionTypeId } from '../enum/TransactionTypeId'
|
||||
import { TransactionType } from '../enum/TransactionType'
|
||||
import { hasUserAmount, isHexPublicKey } from '../../util/validate'
|
||||
@ -68,8 +68,6 @@ async function calculateAndAddDecayTransactions(
|
||||
const userRepository = getCustomRepository(UserRepository)
|
||||
const userIndiced = await userRepository.getUsersIndiced(involvedUsersUnique)
|
||||
|
||||
const decayStartTransaction = await transactionRepository.findDecayStartBlock()
|
||||
|
||||
for (let i = 0; i < userTransactions.length; i++) {
|
||||
const userTransaction = userTransactions[i]
|
||||
const transaction = transactionIndiced[userTransaction.transactionId]
|
||||
@ -82,26 +80,22 @@ async function calculateAndAddDecayTransactions(
|
||||
|
||||
if (previousTransaction) {
|
||||
const currentTransaction = userTransaction
|
||||
const decay = await calculateDecayWithInterval(
|
||||
const decay = await calculateDecay(
|
||||
previousTransaction.balance,
|
||||
previousTransaction.balanceDate,
|
||||
currentTransaction.balanceDate,
|
||||
)
|
||||
const balance = previousTransaction.balance - decay.balance
|
||||
|
||||
if (
|
||||
decayStartTransaction &&
|
||||
decayStartTransaction.received < currentTransaction.balanceDate
|
||||
) {
|
||||
if (CONFIG.DECAY_START_TIME < currentTransaction.balanceDate) {
|
||||
finalTransaction.decay = decay
|
||||
finalTransaction.decay.balance = roundFloorFrom4(balance)
|
||||
if (
|
||||
decayStartTransaction &&
|
||||
previousTransaction.transactionId < decayStartTransaction.id &&
|
||||
currentTransaction.transactionId > decayStartTransaction.id
|
||||
previousTransaction.balanceDate < CONFIG.DECAY_START_TIME &&
|
||||
currentTransaction.balanceDate > CONFIG.DECAY_START_TIME
|
||||
) {
|
||||
finalTransaction.decay.decayStartBlock = (
|
||||
decayStartTransaction.received.getTime() / 1000
|
||||
CONFIG.DECAY_START_TIME.getTime() / 1000
|
||||
).toString()
|
||||
}
|
||||
}
|
||||
@ -148,11 +142,7 @@ async function calculateAndAddDecayTransactions(
|
||||
|
||||
if (i === userTransactions.length - 1 && decay) {
|
||||
const now = new Date()
|
||||
const decay = await calculateDecayWithInterval(
|
||||
userTransaction.balance,
|
||||
userTransaction.balanceDate,
|
||||
now.getTime(),
|
||||
)
|
||||
const decay = await calculateDecay(userTransaction.balance, userTransaction.balanceDate, now)
|
||||
const balance = userTransaction.balance - decay.balance
|
||||
|
||||
const decayTransaction = new Transaction()
|
||||
@ -234,12 +224,8 @@ async function updateStateBalance(
|
||||
balance.amount = centAmount
|
||||
balance.modified = received
|
||||
} else {
|
||||
const decaiedBalance = await calculateDecay(balance.amount, balance.recordDate, received).catch(
|
||||
() => {
|
||||
throw new Error('error by calculating decay')
|
||||
},
|
||||
)
|
||||
balance.amount = Number(decaiedBalance) + centAmount
|
||||
const decayedBalance = calculateDecay(balance.amount, balance.recordDate, received)
|
||||
balance.amount = Number(decayedBalance) + centAmount
|
||||
balance.modified = new Date()
|
||||
}
|
||||
if (balance.amount <= 0) {
|
||||
@ -263,13 +249,11 @@ async function addUserTransaction(
|
||||
const lastUserTransaction = await userTransactionRepository.findLastForUser(user.id)
|
||||
if (lastUserTransaction) {
|
||||
newBalance += Number(
|
||||
await calculateDecay(
|
||||
calculateDecay(
|
||||
Number(lastUserTransaction.balance),
|
||||
lastUserTransaction.balanceDate,
|
||||
transaction.received,
|
||||
).catch(() => {
|
||||
throw new Error('error by calculating decay')
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@ -346,7 +330,7 @@ export class TransactionResolver {
|
||||
const now = new Date()
|
||||
transactions.balance = roundFloorFrom4(balanceEntity.amount)
|
||||
transactions.decay = roundFloorFrom4(
|
||||
await calculateDecay(balanceEntity.amount, balanceEntity.recordDate, now),
|
||||
calculateDecay(balanceEntity.amount, balanceEntity.recordDate, now).balance,
|
||||
)
|
||||
transactions.decayDate = now.toString()
|
||||
}
|
||||
|
||||
@ -3,13 +3,6 @@ import { Transaction } from '@entity/Transaction'
|
||||
|
||||
@EntityRepository(Transaction)
|
||||
export class TransactionRepository extends Repository<Transaction> {
|
||||
async findDecayStartBlock(): Promise<Transaction | undefined> {
|
||||
return this.createQueryBuilder('transaction')
|
||||
.where('transaction.transactionTypeId = :transactionTypeId', { transactionTypeId: 9 })
|
||||
.orderBy('received', 'ASC')
|
||||
.getOne()
|
||||
}
|
||||
|
||||
async joinFullTransactionsByIds(transactionIds: number[]): Promise<Transaction[]> {
|
||||
return this.createQueryBuilder('transaction')
|
||||
.where('transaction.id IN (:...transactions)', { transactions: transactionIds })
|
||||
|
||||
@ -1,70 +1,46 @@
|
||||
import { getCustomRepository } from '@dbTools/typeorm'
|
||||
import CONFIG from '../config'
|
||||
import { Decay } from '../graphql/model/Decay'
|
||||
import { TransactionRepository } from '../typeorm/repository/Transaction'
|
||||
|
||||
function decayFormula(amount: number, seconds: number): number {
|
||||
return amount * Math.pow(0.99999997802044727, seconds) // This number represents 50% decay a year
|
||||
}
|
||||
|
||||
async function calculateDecay(amount: number, from: Date, to: Date): Promise<number> {
|
||||
if (amount === undefined || !from || !to) {
|
||||
throw new Error('at least one parameter is undefined')
|
||||
function calculateDecay(amount: number, from: Date, to: Date): Decay {
|
||||
const fromMs = from.getTime()
|
||||
const toMs = to.getTime()
|
||||
const decayStartBlockMs = CONFIG.DECAY_START_TIME.getTime()
|
||||
|
||||
if (toMs < fromMs) {
|
||||
throw new Error('to < from, reverse decay calculation is invalid')
|
||||
}
|
||||
if (from === to) {
|
||||
return amount
|
||||
|
||||
// Initialize with no decay
|
||||
const decay = new Decay({
|
||||
balance: amount,
|
||||
decayStart: null,
|
||||
decayEnd: null,
|
||||
decayDuration: 0,
|
||||
decayStartBlock: (decayStartBlockMs / 1000).toString(),
|
||||
})
|
||||
|
||||
// decay started after end date; no decay
|
||||
if (decayStartBlockMs > toMs) {
|
||||
return decay
|
||||
}
|
||||
if (to < from) {
|
||||
throw new Error('to < from, so the target date is in the past?')
|
||||
// decay started before start date; decay for full duration
|
||||
else if (decayStartBlockMs < fromMs) {
|
||||
decay.decayStart = (fromMs / 1000).toString()
|
||||
decay.decayDuration = (toMs - fromMs) / 1000
|
||||
}
|
||||
// load decay start block
|
||||
const transactionRepository = getCustomRepository(TransactionRepository)
|
||||
const decayStartBlock = await transactionRepository.findDecayStartBlock()
|
||||
|
||||
// if decay hasn't started yet we return input amount
|
||||
if (!decayStartBlock) return amount
|
||||
|
||||
// what happens when from > to
|
||||
// Do we want to have negative decay?
|
||||
const decayDuration = (to.getTime() - from.getTime()) / 1000
|
||||
return decayFormula(amount, decayDuration)
|
||||
}
|
||||
|
||||
async function calculateDecayWithInterval(
|
||||
amount: number,
|
||||
from: number | Date,
|
||||
to: number | Date,
|
||||
): Promise<Decay> {
|
||||
const transactionRepository = getCustomRepository(TransactionRepository)
|
||||
const decayStartBlock = await transactionRepository.findDecayStartBlock()
|
||||
|
||||
const result = new Decay(undefined)
|
||||
result.balance = amount
|
||||
const fromMillis = typeof from === 'number' ? from : from.getTime()
|
||||
const toMillis = typeof to === 'number' ? to : to.getTime()
|
||||
result.decayStart = (fromMillis / 1000).toString()
|
||||
result.decayEnd = (toMillis / 1000).toString()
|
||||
|
||||
// (amount, from.getTime(), to.getTime())
|
||||
|
||||
// if no decay start block exist or decay startet after end date
|
||||
if (!decayStartBlock || decayStartBlock.received.getTime() > toMillis) {
|
||||
return result
|
||||
}
|
||||
const decayStartBlockMillis = decayStartBlock.received.getTime()
|
||||
|
||||
// if decay start date is before start date we calculate decay for full duration
|
||||
if (decayStartBlockMillis < fromMillis) {
|
||||
result.decayDuration = toMillis - fromMillis
|
||||
}
|
||||
// if decay start in between start date and end date we caculcate decay from decay start time to end date
|
||||
// decay started between start and end date; decay from decay start till end date
|
||||
else {
|
||||
result.decayDuration = toMillis - decayStartBlockMillis
|
||||
result.decayStart = (decayStartBlockMillis / 1000).toString()
|
||||
decay.decayStart = (decayStartBlockMs / 1000).toString()
|
||||
decay.decayDuration = (toMs - decayStartBlockMs) / 1000
|
||||
}
|
||||
// js use timestamp in milliseconds but we calculate with seconds
|
||||
result.decayDuration /= 1000
|
||||
result.balance = decayFormula(amount, result.decayDuration)
|
||||
return result
|
||||
|
||||
decay.decayEnd = (toMs / 1000).toString()
|
||||
decay.balance = decayFormula(amount, decay.decayDuration)
|
||||
return decay
|
||||
}
|
||||
|
||||
export { decayFormula, calculateDecay, calculateDecayWithInterval }
|
||||
export { decayFormula, calculateDecay }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user