import { Action } from '../display/action.js'; import { PostMessage } from '../forum-network/message.js'; import { CryptoUtil } from '../supporting/crypto.js'; import { ReputationHolder } from '../reputation/reputation-holder.js'; import { EdgeTypes } from '../../util/constants.js'; import { displayNumber } from '../../util/helpers.js'; export class Expert extends ReputationHolder { constructor(dao, name, scene, options) { super(name, scene, options); this.dao = dao; this.actions = { submitPostViaNetwork: new Action('submit post via network', scene), submitPost: new Action('submit post', scene), initiateValidationPool: new Action('initiate validation pool', scene), stake: new Action('stake on post', scene), registerAvailability: new Action('register availability', scene), getAssignedWork: new Action('get assigned work', scene), submitWork: new Action('submit work evidence', scene), }; this.validationPools = new Map(); this.tokens = []; } getReputation() { const authorVertex = this.dao.forum.graph.getVertex(this.reputationPublicKey); if (!authorVertex) { return 0; } const authorEdges = authorVertex.getEdges(EdgeTypes.AUTHOR, false); const tokenValues = authorEdges.map(({ data: { tokenId } }) => this.dao.reputation.valueOf(tokenId)); return tokenValues.reduce((value, total) => total += value, 0); } getLabel() { return `${this.name}
reputation ${displayNumber(this.getReputation())}
` .replaceAll(/\n\s*/g, ''); } async initialize() { this.reputationKey = await CryptoUtil.generateAsymmetricKey(); // this.reputationPublicKey = await CryptoUtil.exportKey(this.reputationKey.publicKey); this.reputationPublicKey = this.name; this.status.set('Initialized'); return this; } async submitPostWithFee(postContent, poolOptions) { const post = await this.dao.forum.addPost(this.reputationPublicKey, postContent); await this.actions.submitPost.log(this, post); const postId = post.id; const pool = await this.initiateValidationPool({ ...poolOptions, postId }); this.tokens.push(pool.tokenId); return { postId, pool }; } async initiateValidationPool(poolOptions) { // For now, make direct call rather than network poolOptions.reputationPublicKey = this.reputationPublicKey; const pool = await this.dao.initiateValidationPool(this, poolOptions); this.tokens.push(pool.tokenId); this.validationPools.set(pool.id, poolOptions); return pool; } async stake(validationPool, { position, amount, lockingTime, }) { // TODO: encrypt stake // TODO: sign message await this.actions.stake.log( this, validationPool, `(${position ? 'for' : 'against'}, stake: ${amount})`, ); return validationPool.stake(this.reputationPublicKey, { position, amount, lockingTime, tokenId: this.tokens[0], }); } async registerAvailability(stakeAmount, duration) { await this.actions.registerAvailability.log( this, this.dao.availability, `(stake: ${stakeAmount}, duration: ${duration})`, ); this.workerId = await this.dao.availability.register(this.reputationPublicKey, { stakeAmount, tokenId: this.tokens[0], duration, }); } async getAssignedWork() { const requestId = await this.dao.availability.getAssignedWork(this.workerId); const request = await this.dao.business.getRequest(requestId); return request; } async submitWork(requestId, evidence, { tokenLossRatio, duration }) { await this.actions.submitWork.log(this, this.dao.business); return this.dao.business.submitWork(this.reputationPublicKey, requestId, evidence, { tokenLossRatio, duration }); } }