dao-governance-framework/forum-network/public/classes/reputation.js

86 lines
2.1 KiB
JavaScript

class Lock {
constructor(tokens, duration) {
this.dateCreated = new Date();
this.tokens = tokens;
this.duration = duration;
}
}
class Reputation {
constructor() {
this.tokens = 0;
this.locks = new Set();
}
addTokens(tokens) {
if (this.tokens + tokens < 0) {
throw new Error(`Token balance can not become negative`);
}
this.tokens += tokens;
}
lockTokens(tokens, duration) {
if (tokens > this.getAvailableTokens()) {
throw new Error("Can not lock more tokens than are available")
}
const lock = new Lock(tokens, duration);
this.locks.add(lock);
// TODO: Prune locks once expired
}
getTokens() {
return this.tokens;
}
getAvailableTokens() {
const now = new Date();
const tokensLocked = Array.from(this.locks.values())
.filter(({dateCreated, duration}) => now - dateCreated < duration)
.reduce((acc, cur) => acc += cur.tokens, 0);
return Math.max(this.tokens - tokensLocked, 0);
}
}
export class Reputations extends Map {
getTokens(reputationPublicKey) {
const reputation = this.get(reputationPublicKey);
if (!reputation) {
return 0;
}
return reputation.getTokens();
}
getAvailableTokens(reputationPublicKey) {
const reputation = this.get(reputationPublicKey);
if (!reputation) {
return 0;
}
return reputation.getAvailableTokens();
}
addTokens(reputationPublicKey, tokens) {
const reputation = this.get(reputationPublicKey) ?? new Reputation();
reputation.addTokens(tokens);
this.set(reputationPublicKey, reputation);
}
lockTokens(reputationPublicKey, tokens, duration) {
if (!tokens || !duration) {
return;
}
const reputation = this.get(reputationPublicKey);
if (!reputation) {
throw new Error(`${reputationPublicKey} has no tokens to lock`);
}
reputation.lockTokens(tokens, duration);
}
getTotal() {
return Array.from(this.values()).reduce((acc, cur) => acc += cur.getTokens(), 0);
}
getTotalAvailable() {
return Array.from(this.values()).reduce((acc, cur) => acc += cur.getAvailableTokens(), 0);
}
}