import { Box } from '../../classes/box.js'; import { Scene } from '../../classes/scene.js'; import { Expert } from '../../classes/expert.js'; import { delay } from '../../util.js'; import { DAO } from '../../classes/dao.js'; import { Public } from '../../classes/public.js'; import { PostContent } from '../../classes/post-content.js'; const DELAY_INTERVAL = 500; let dao; let experts; let requestor; const newExpert = async () => { const index = experts.length; const name = `Expert${index + 1}`; const expert = await new Expert(dao, name).initialize(); experts.push(expert); return expert; }; async function setup() { const rootElement = document.getElementById('scene'); const rootBox = new Box('rootBox', rootElement).flex(); const scene = (window.scene = new Scene('Availability test', rootBox)); scene.withSequenceDiagram(); scene.withFlowchart(); scene.withTable(); experts = (window.experts = []); dao = (window.dao = new DAO('DGF')); await newExpert(); await newExpert(); requestor = new Public('Public'); } const updateDisplayValues = async () => { for (const expert of experts) { await expert.setValue( 'rep', dao.reputation.valueOwnedBy(expert.reputationPublicKey), ); } await dao.setValue('total rep', dao.reputation.getTotal()); await window.scene.sequence.render(); }; const updateDisplayValuesAndDelay = async (delayMs = DELAY_INTERVAL) => { await updateDisplayValues(); await delay(delayMs); }; const getActiveWorker = async () => { let worker; let request; for (const expert of experts) { request = await expert.getAssignedWork(); if (request) { worker = expert; await worker.actions.getAssignedWork.log(worker, dao.availability); worker.activate(); break; } } return { worker, request }; }; const voteForWorkEvidence = async (worker, pool) => { for (const expert of experts) { if (expert !== worker) { await expert.stake(pool, { position: true, amount: 1, }); } } }; await setup(); await updateDisplayValuesAndDelay(); // Experts gain initial reputation by submitting a post with fee const { postId: postId1, pool: pool1 } = await experts[0].submitPostWithFee( new PostContent({ hello: 'there' }).setTitle('Post 1'), { fee: 10, duration: 1000, tokenLossRatio: 1, }, ); await updateDisplayValuesAndDelay(1000); await pool1.evaluateWinningConditions(); await updateDisplayValuesAndDelay(); const { pool: pool2 } = await experts[1].submitPostWithFee( new PostContent({ hello: 'to you as well' }) .setTitle('Post 2') .addCitation(postId1, 0.5), { fee: 10, duration: 1000, tokenLossRatio: 1, }, ); await updateDisplayValuesAndDelay(1000); await pool2.evaluateWinningConditions(); await updateDisplayValuesAndDelay(); // Populate availability pool await experts[0].registerAvailability(1, 10000); await experts[1].registerAvailability(1, 10000); await updateDisplayValuesAndDelay(); // Submit work request await requestor.submitRequest( dao.business, { fee: 100 }, { please: 'do some work' }, ); await updateDisplayValuesAndDelay(); // Receive work request const { worker, request } = await getActiveWorker(); // Submit work evidence const pool = await worker.submitWork( request.id, { here: 'is some evidence of work product', }, { tokenLossRatio: 1, duration: 1000, }, ); worker.deactivate(); await updateDisplayValuesAndDelay(); // Stake on work evidence await voteForWorkEvidence(worker, pool); await updateDisplayValuesAndDelay(); // Wait for validation pool duration to elapse await delay(1000); // Distribute reputation awards and fees await pool.evaluateWinningConditions(); await updateDisplayValuesAndDelay(); // This should throw an exception since the pool is already resolved try { await pool.evaluateWinningConditions(); } catch (e) { if (e.message.match(/Validation pool has already been resolved/)) { console.log( 'Caught expected error: Validation pool has already been resolved', ); } else { console.error('Unexpected error'); throw e; } }