gradido/backend/src/util/decay.ts

64 lines
1.7 KiB
TypeScript

import Decimal from 'decimal.js-light'
import CONFIG from '@/config'
import { Decay } from '@model/Decay'
// TODO: externalize all those definitions and functions into an external decay library
function decayFormula(value: Decimal, seconds: number): Decimal {
// TODO why do we need to convert this here to a stting to work properly?
return value.mul(
new Decimal('0.99999997803504048973201202316767079413460520837376').pow(seconds).toString(),
)
}
function calculateDecay(
amount: Decimal,
from: Date,
to: Date,
startBlock: Date = CONFIG.DECAY_START_TIME,
): Decay {
const fromMs = from.getTime()
const toMs = to.getTime()
const startBlockMs = startBlock.getTime()
if (toMs < fromMs) {
throw new Error('to < from, reverse decay calculation is invalid')
}
// Initialize with no decay
const decay: Decay = {
balance: amount,
decay: new Decimal(0),
roundedDecay: new Decimal(0),
start: null,
end: null,
duration: null,
}
// decay started after end date; no decay
if (startBlockMs > toMs) {
return decay
}
// decay started before start date; decay for full duration
if (startBlockMs < fromMs) {
decay.start = from
decay.duration = (toMs - fromMs) / 1000
}
// decay started between start and end date; decay from decay start till end date
else {
decay.start = startBlock
decay.duration = (toMs - startBlockMs) / 1000
}
decay.end = to
decay.balance = decayFormula(amount, decay.duration)
decay.decay = decay.balance.minus(amount)
decay.roundedDecay = amount
.toDecimalPlaces(2, Decimal.ROUND_DOWN)
.minus(decay.balance.toDecimalPlaces(2, Decimal.ROUND_DOWN).toString())
.mul(-1)
return decay
}
export { decayFormula, calculateDecay }