Improved seq diag logging
This commit is contained in:
parent
c89ba51dab
commit
41506fdcd5
|
@ -7,6 +7,21 @@ export class Actor {
|
||||||
this.status.set('New');
|
this.status.set('New');
|
||||||
this.scene.log(`participant ${this.name}`);
|
this.scene.log(`participant ${this.name}`);
|
||||||
this.values = new Map();
|
this.values = new Map();
|
||||||
|
this.active = 0;
|
||||||
|
this.scene.registerActor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
this.active += 1;
|
||||||
|
this.scene.log(`activate ${this.name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
deactivate() {
|
||||||
|
if (!this.active) {
|
||||||
|
throw new Error(`${this.name} is not active, can not deactivate`);
|
||||||
|
}
|
||||||
|
this.active -= 1;
|
||||||
|
this.scene.log(`deactivate ${this.name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
send(dest, action, detail) {
|
send(dest, action, detail) {
|
||||||
|
@ -47,6 +62,9 @@ export class Actor {
|
||||||
displayValue = this.scene.addDisplayValue(`${this.name} ${label}`);
|
displayValue = this.scene.addDisplayValue(`${this.name} ${label}`);
|
||||||
this.values.set(label, displayValue);
|
this.values.set(label, displayValue);
|
||||||
}
|
}
|
||||||
|
if (value !== displayValue.get()) {
|
||||||
|
this.scene.log(`note over ${this.name} : ${label} = ${value}`);
|
||||||
|
}
|
||||||
displayValue.set(value);
|
displayValue.set(value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import { Actor } from "./actor.js";
|
import { Actor } from "./actor.js";
|
||||||
import { Reputations } from "./reputation.js";
|
import { Reputations } from "./reputation.js";
|
||||||
import { ValidationPool } from "./validation-pool.js";
|
import { ValidationPool } from "./validation-pool.js";
|
||||||
import { Vote } from "./vote.js";
|
|
||||||
import { Voter } from "./voter.js";
|
|
||||||
import params from "./params.js";
|
import params from "./params.js";
|
||||||
|
import { Action } from "./action.js";
|
||||||
|
|
||||||
export class Bench extends Actor {
|
export class Bench extends Actor {
|
||||||
constructor(name, scene) {
|
constructor(name, scene) {
|
||||||
|
@ -13,7 +12,10 @@ export class Bench extends Actor {
|
||||||
this.reputations = new Reputations();
|
this.reputations = new Reputations();
|
||||||
|
|
||||||
this.actions = {
|
this.actions = {
|
||||||
|
createValidationPool: new Action('create validation pool', scene),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
listValidationPools() {
|
listValidationPools() {
|
||||||
|
@ -51,22 +53,12 @@ export class Bench extends Actor {
|
||||||
}
|
}
|
||||||
|
|
||||||
initiateValidationPool(authorId, {fee, duration, tokenLossRatio, contentiousDebate}) {
|
initiateValidationPool(authorId, {fee, duration, tokenLossRatio, contentiousDebate}) {
|
||||||
const vote = new ValidationPool(this, authorId, {fee, duration, tokenLossRatio, contentiousDebate});
|
const validationPoolNumber = this.validationPools.size + 1;
|
||||||
this.validationPools.set(vote.id, vote);
|
const validationPool = new ValidationPool(this, authorId, {fee, duration, tokenLossRatio, contentiousDebate},
|
||||||
return vote.id;
|
`pool${validationPoolNumber}`, scene);
|
||||||
}
|
this.validationPools.set(validationPool.id, validationPool);
|
||||||
|
this.actions.createValidationPool.log(this, validationPool)
|
||||||
castVote(voteId, signingPublicKey, position, stake, lockingTime) {
|
validationPool.activate();
|
||||||
const vote = new Vote(position, stake, lockingTime);
|
return validationPool;
|
||||||
const validationPool = this.validationPools.get(voteId);
|
|
||||||
validationPool.castVote(signingPublicKey, vote);
|
|
||||||
}
|
|
||||||
|
|
||||||
revealIdentity(voteId, signingPublicKey, reputationPublicKey) {
|
|
||||||
const validationPool = this.validationPools.get(voteId);
|
|
||||||
const voter = this.voters.get(reputationPublicKey) ?? new Voter(reputationPublicKey);
|
|
||||||
voter.addVoteRecord(validationPool);
|
|
||||||
this.voters.set(reputationPublicKey, voter);
|
|
||||||
validationPool.revealIdentity(signingPublicKey, voter);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,18 @@ export class Member extends Actor {
|
||||||
super(name, scene);
|
super(name, scene);
|
||||||
this.actions = {
|
this.actions = {
|
||||||
submitPost: new Action('submit post', scene),
|
submitPost: new Action('submit post', scene),
|
||||||
initiateValidationPool: new Action('initiate vote', scene),
|
initiateValidationPool: new Action('initiate validation pool', scene),
|
||||||
castVote: new Action('cast vote', scene),
|
castVote: new Action('cast vote', scene),
|
||||||
revealIdentity: new Action('reveal identity', scene),
|
revealIdentity: new Action('reveal identity', scene),
|
||||||
};
|
};
|
||||||
this.votes = new Map();
|
this.validationPools = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
async initialize() {
|
async initialize() {
|
||||||
this.reputationKey = await CryptoUtil.generateAsymmetricKey();
|
this.reputationKey = await CryptoUtil.generateAsymmetricKey();
|
||||||
this.reputationPublicKey = await CryptoUtil.exportKey(this.reputationKey.publicKey);
|
this.reputationPublicKey = await CryptoUtil.exportKey(this.reputationKey.publicKey);
|
||||||
this.status.set('Initialized');
|
this.status.set('Initialized');
|
||||||
|
this.activate();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,20 +38,20 @@ export class Member extends Actor {
|
||||||
return bench.initiateValidationPool(this.reputationPublicKey, options);
|
return bench.initiateValidationPool(this.reputationPublicKey, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async castVote(validationPool, voteId, position, stake, lockingTime) {
|
async castVote(validationPool, position, stake, lockingTime) {
|
||||||
const signingKey = await CryptoUtil.generateAsymmetricKey();
|
const signingKey = await CryptoUtil.generateAsymmetricKey();
|
||||||
const signingPublicKey = await CryptoUtil.exportKey(signingKey.publicKey)
|
const signingPublicKey = await CryptoUtil.exportKey(signingKey.publicKey)
|
||||||
this.votes.set(voteId, {signingPublicKey});
|
this.validationPools.set(validationPool.id, {signingPublicKey});
|
||||||
// TODO: encrypt vote
|
// TODO: encrypt vote
|
||||||
// TODO: sign message
|
// TODO: sign message
|
||||||
this.actions.castVote.log(this, validationPool);
|
this.actions.castVote.log(this, validationPool);
|
||||||
validationPool.castVote(voteId, signingPublicKey, position, stake, lockingTime);
|
validationPool.castVote(signingPublicKey, position, stake, lockingTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
async revealIdentity(validationPool, voteId) {
|
async revealIdentity(validationPool) {
|
||||||
const {signingPublicKey} = this.votes.get(voteId);
|
const {signingPublicKey} = this.validationPools.get(validationPool.id);
|
||||||
// TODO: sign message
|
// TODO: sign message
|
||||||
this.actions.revealIdentity.log(this, validationPool);
|
this.actions.revealIdentity.log(this, validationPool);
|
||||||
validationPool.revealIdentity(voteId, signingPublicKey, this.reputationPublicKey);
|
validationPool.revealIdentity(signingPublicKey, this.reputationPublicKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,7 @@ class Reputation {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const tokensLocked = Array.from(this.locks.values())
|
const tokensLocked = Array.from(this.locks.values())
|
||||||
.filter(({dateCreated, duration}) => now - dateCreated < duration)
|
.filter(({dateCreated, duration}) => now - dateCreated < duration)
|
||||||
.map(({tokens}) => tokens)
|
.reduce((acc, cur) => acc += cur.tokens, 0);
|
||||||
.reduce((acc, cur) => acc += cur, 0);
|
|
||||||
return Math.max(this.tokens - tokensLocked, 0);
|
return Math.max(this.tokens - tokensLocked, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ export class Scene {
|
||||||
this.displayValuesBox = this.box.addBox(`${this.name}-values`);
|
this.displayValuesBox = this.box.addBox(`${this.name}-values`);
|
||||||
this.box.addBox('Spacer').setInnerHTML(' ');
|
this.box.addBox('Spacer').setInnerHTML(' ');
|
||||||
this.logBox = this.box.addBox(`${this.name}-log`);
|
this.logBox = this.box.addBox(`${this.name}-log`);
|
||||||
|
this.actors = new Set();
|
||||||
// this.seqDiagramContainer = this.box.addBox(`${this.name}-seq-diagram-container`);
|
// this.seqDiagramContainer = this.box.addBox(`${this.name}-seq-diagram-container`);
|
||||||
// this.seqDiagramBox = this.box.addBox(`${this.name}-seq-diagram`);
|
// this.seqDiagramBox = this.box.addBox(`${this.name}-seq-diagram`);
|
||||||
// mermaid.mermaidAPI.initialize({ startOnLoad: false });
|
// mermaid.mermaidAPI.initialize({ startOnLoad: false });
|
||||||
|
@ -21,6 +22,10 @@ export class Scene {
|
||||||
return actor;
|
return actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerActor(actor) {
|
||||||
|
this.actors.add(actor);
|
||||||
|
}
|
||||||
|
|
||||||
addAction(name) {
|
addAction(name) {
|
||||||
const action = new Action(name, this);
|
const action = new Action(name, this);
|
||||||
return action;
|
return action;
|
||||||
|
@ -36,6 +41,15 @@ export class Scene {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deactivateAll() {
|
||||||
|
for (const actor of this.actors.values()) {
|
||||||
|
console.log(actor);
|
||||||
|
while (actor.active) {
|
||||||
|
actor.deactivate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// async renderSequenceDiagram() {
|
// async renderSequenceDiagram() {
|
||||||
// await mermaid.mermaidAPI.render(
|
// await mermaid.mermaidAPI.render(
|
||||||
// `${this.name}-seq-diagram-element`,
|
// `${this.name}-seq-diagram-element`,
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import { CryptoUtil } from "./crypto.js";
|
import { CryptoUtil } from "./crypto.js";
|
||||||
|
import { Vote } from "./vote.js";
|
||||||
|
import { Voter } from "./voter.js";
|
||||||
|
import { Actor } from "./actor.js";
|
||||||
import params from "./params.js";
|
import params from "./params.js";
|
||||||
|
|
||||||
const ValidationPoolStates = Object.freeze({
|
const ValidationPoolStates = Object.freeze({
|
||||||
|
@ -6,8 +9,9 @@ const ValidationPoolStates = Object.freeze({
|
||||||
CLOSED: "CLOSED",
|
CLOSED: "CLOSED",
|
||||||
});
|
});
|
||||||
|
|
||||||
export class ValidationPool {
|
export class ValidationPool extends Actor {
|
||||||
constructor(validationPool, authorId, {fee, duration, tokenLossRatio, contentiousDebate = false}) {
|
constructor(bench, authorId, {fee, duration, tokenLossRatio, contentiousDebate = false}, name, scene) {
|
||||||
|
super(name, scene);
|
||||||
// If contentiousDebate = true, we will follow the progression defined by getTokenLossRatio()
|
// If contentiousDebate = true, we will follow the progression defined by getTokenLossRatio()
|
||||||
if (!contentiousDebate && (tokenLossRatio < 0 || tokenLossRatio > 1 || [null, undefined].includes(tokenLossRatio))) {
|
if (!contentiousDebate && (tokenLossRatio < 0 || tokenLossRatio > 1 || [null, undefined].includes(tokenLossRatio))) {
|
||||||
throw new Error(`Token loss ratio must be in the range [0, 1]; got ${tokenLossRatio}`)
|
throw new Error(`Token loss ratio must be in the range [0, 1]; got ${tokenLossRatio}`)
|
||||||
|
@ -18,7 +22,7 @@ export class ValidationPool {
|
||||||
this.state = ValidationPoolStates.OPEN;
|
this.state = ValidationPoolStates.OPEN;
|
||||||
this.votes = new Map();
|
this.votes = new Map();
|
||||||
this.voters = new Map();
|
this.voters = new Map();
|
||||||
this.validationPool = validationPool;
|
this.bench = bench;
|
||||||
this.id = CryptoUtil.randomUUID();
|
this.id = CryptoUtil.randomUUID();
|
||||||
this.dateStart = new Date();
|
this.dateStart = new Date();
|
||||||
this.authorId = authorId;
|
this.authorId = authorId;
|
||||||
|
@ -33,12 +37,13 @@ export class ValidationPool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
castVote(signingPublicKey, vote) {
|
castVote(signingPublicKey, position, stake, lockingTime) {
|
||||||
|
const vote = new Vote(position, stake, lockingTime);
|
||||||
if (this.state === ValidationPoolStates.CLOSED) {
|
if (this.state === ValidationPoolStates.CLOSED) {
|
||||||
throw new Error(`Vote ${this.id} is closed`);
|
throw new Error(`Validation pool ${this.id} is closed`);
|
||||||
}
|
}
|
||||||
if (this.duration && new Date() - this.dateStart > this.duration) {
|
if (this.duration && new Date() - this.dateStart > this.duration) {
|
||||||
throw new Error(`Vote ${this.id} has expired, no new votes may be cast`);
|
throw new Error(`Validation pool ${this.id} has expired, no new votes may be cast`);
|
||||||
}
|
}
|
||||||
this.votes.set(signingPublicKey, vote);
|
this.votes.set(signingPublicKey, vote);
|
||||||
}
|
}
|
||||||
|
@ -48,10 +53,13 @@ export class ValidationPool {
|
||||||
.filter(([_, vote]) => vote.position === position));
|
.filter(([_, vote]) => vote.position === position));
|
||||||
}
|
}
|
||||||
|
|
||||||
revealIdentity(signingPublicKey, voter) {
|
revealIdentity(signingPublicKey, reputationPublicKey) {
|
||||||
if (!this.votes.get(signingPublicKey)) {
|
if (!this.votes.get(signingPublicKey)) {
|
||||||
throw new Error("Must vote before revealing identity");
|
throw new Error("Must vote before revealing identity");
|
||||||
}
|
}
|
||||||
|
const voter = this.bench.voters.get(reputationPublicKey) ?? new Voter(reputationPublicKey);
|
||||||
|
voter.addVoteRecord(this);
|
||||||
|
this.bench.voters.set(reputationPublicKey, voter);
|
||||||
this.voters.set(signingPublicKey, voter);
|
this.voters.set(signingPublicKey, voter);
|
||||||
if (this.votes.size === this.voters.size) {
|
if (this.votes.size === this.voters.size) {
|
||||||
// All voters have revealed their reputation public keys
|
// All voters have revealed their reputation public keys
|
||||||
|
@ -60,6 +68,7 @@ export class ValidationPool {
|
||||||
const result = this.evaluateWinningConditions();
|
const result = this.evaluateWinningConditions();
|
||||||
this.applyTokenLocking();
|
this.applyTokenLocking();
|
||||||
this.distributeTokens(result);
|
this.distributeTokens(result);
|
||||||
|
this.deactivate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +100,7 @@ export class ValidationPool {
|
||||||
// specified amounts of time.
|
// specified amounts of time.
|
||||||
for (const [signingPublicKey, {stake, lockingTime}] of this.votes.entries()) {
|
for (const [signingPublicKey, {stake, lockingTime}] of this.votes.entries()) {
|
||||||
const voter = this.voters.get(signingPublicKey);
|
const voter = this.voters.get(signingPublicKey);
|
||||||
this.validationPool.reputations.lockTokens(voter.reputationPublicKey, stake, lockingTime);
|
this.bench.reputations.lockTokens(voter.reputationPublicKey, stake, lockingTime);
|
||||||
// TODO: If there is an exception here, the voter may have voted incorrectly. Consider penalties.
|
// TODO: If there is an exception here, the voter may have voted incorrectly. Consider penalties.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,12 +112,13 @@ export class ValidationPool {
|
||||||
|
|
||||||
const upvoteValue = getTotalValue(true);
|
const upvoteValue = getTotalValue(true);
|
||||||
const downvoteValue = getTotalValue(false);
|
const downvoteValue = getTotalValue(false);
|
||||||
const activeAvailableReputation = this.validationPool.getTotalActiveAvailableReputation();
|
const activeAvailableReputation = this.bench.getTotalActiveAvailableReputation();
|
||||||
const votePasses = upvoteValue >= params.winningRatio * downvoteValue;
|
const votePasses = upvoteValue >= params.winningRatio * downvoteValue;
|
||||||
const quorumMet = upvoteValue + downvoteValue >= params.quorum * activeAvailableReputation;
|
const quorumMet = upvoteValue + downvoteValue >= params.quorum * activeAvailableReputation;
|
||||||
|
|
||||||
// TODO: If quorum is not met, what should happen?
|
// TODO: If quorum is not met, what should happen?
|
||||||
if (!quorumMet) {
|
if (!quorumMet) {
|
||||||
|
this.deactivate();
|
||||||
throw new Error("Quorum is not met");
|
throw new Error("Quorum is not met");
|
||||||
}
|
}
|
||||||
return votePasses && quorumMet;
|
return votePasses && quorumMet;
|
||||||
|
@ -117,7 +127,7 @@ export class ValidationPool {
|
||||||
distributeTokens(result) {
|
distributeTokens(result) {
|
||||||
// Reward the author
|
// Reward the author
|
||||||
// TODO: Penalty to the author if the vote does not pass?
|
// TODO: Penalty to the author if the vote does not pass?
|
||||||
this.validationPool.reputations.addTokens(this.authorId, this.tokens.author);
|
this.bench.reputations.addTokens(this.authorId, this.tokens.author);
|
||||||
// Reward the vote winners, in proportion to their stakes
|
// Reward the vote winners, in proportion to their stakes
|
||||||
const tokensForWinners = result ? this.tokens.for : this.tokens.against;
|
const tokensForWinners = result ? this.tokens.for : this.tokens.against;
|
||||||
const winningVotes = this.listVotes(result);
|
const winningVotes = this.listVotes(result);
|
||||||
|
@ -129,7 +139,7 @@ export class ValidationPool {
|
||||||
for (const [signingPublicKey, {stake}] of winningVotes.entries()) {
|
for (const [signingPublicKey, {stake}] of winningVotes.entries()) {
|
||||||
const {reputationPublicKey} = this.voters.get(signingPublicKey);
|
const {reputationPublicKey} = this.voters.get(signingPublicKey);
|
||||||
const reward = tokensForWinners * stake / totalStakes;
|
const reward = tokensForWinners * stake / totalStakes;
|
||||||
this.validationPool.reputations.addTokens(reputationPublicKey, reward);
|
this.bench.reputations.addTokens(reputationPublicKey, reward);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<head>
|
<head>
|
||||||
<title>Forum Network</title>
|
<title>Forum Network</title>
|
||||||
<script type="module" src="./index.js" defer></script>
|
|
||||||
<link type="text/css" rel="stylesheet" href="./index.css" />
|
<link type="text/css" rel="stylesheet" href="./index.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -10,5 +9,6 @@
|
||||||
<li><a href="./forum-test.html">Forum test</a></li>
|
<li><a href="./forum-test.html">Forum test</a></li>
|
||||||
<li><a href="./graph-test.html">Graph test</a></li>
|
<li><a href="./graph-test.html">Graph test</a></li>
|
||||||
<li><a href="./validation-pool-test.html">Validation Pool test</a></li>
|
<li><a href="./validation-pool-test.html">Validation Pool test</a></li>
|
||||||
|
<li><a href="./mermaid-test.html">Mermaid test</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<title>Forum Network</title>
|
||||||
|
<link type="text/css" rel="stylesheet" href="./index.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
|
|
@ -14,8 +14,8 @@ const scene = window.scene = new Scene('Validation Pool test', rootBox).log('seq
|
||||||
|
|
||||||
const bench = window.bench = new Bench("Bench", scene);
|
const bench = window.bench = new Bench("Bench", scene);
|
||||||
|
|
||||||
const member1 = window.member1 = await new Member("member1", scene).initialize();
|
const member1 = window.member1 = await new Member("Member1", scene).initialize();
|
||||||
const member2 = window.member2 = await new Member("member2", scene).initialize();
|
const member2 = window.member2 = await new Member("Member2", scene).initialize();
|
||||||
|
|
||||||
const updateDisplayValues = () => {
|
const updateDisplayValues = () => {
|
||||||
member1.setValue('rep', bench.reputations.getTokens(member1.reputationPublicKey));
|
member1.setValue('rep', bench.reputations.getTokens(member1.reputationPublicKey));
|
||||||
|
@ -27,24 +27,42 @@ const updateDisplayValues = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
updateDisplayValues();
|
updateDisplayValues();
|
||||||
|
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
|
|
||||||
// First member can self-approve
|
// First member can self-approve
|
||||||
const vote1 = member1.initiateValidationPool(bench, {fee: 1, duration: 1000, tokenLossRatio: 1});
|
{
|
||||||
await member1.castVote(bench, vote1, true, 0, 0);
|
const pool = member1.initiateValidationPool(bench, {fee: 1, duration: 1000, tokenLossRatio: 1});
|
||||||
await member1.revealIdentity(bench, vote1); // Vote passes
|
await member1.castVote(pool, true, 0, 0);
|
||||||
|
await member1.revealIdentity(pool); // Vote passes
|
||||||
updateDisplayValues();
|
updateDisplayValues();
|
||||||
|
|
||||||
// const vote2 = member2.initiateValidationPool(bench, {fee: 1, duration: 1000, tokenLossRatio: 1});
|
|
||||||
// await member2.castVote(bench, vote2, true, 0);
|
|
||||||
// await member2.revealIdentity(bench, vote2); // Quorum is not met!
|
|
||||||
|
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failure example: second member can not self-approve
|
||||||
|
try {
|
||||||
|
const pool = member2.initiateValidationPool(bench, {fee: 1, duration: 1000, tokenLossRatio: 1});
|
||||||
|
await member2.castVote(pool, true, 0, 0);
|
||||||
|
await member2.revealIdentity(pool); // Quorum not met!
|
||||||
|
updateDisplayValues();
|
||||||
|
await delay(1000);
|
||||||
|
} catch(e) {
|
||||||
|
if (e.message.match(/Quorum is not met/)) {
|
||||||
|
console.log("Caught expected error: Quorum not met")
|
||||||
|
} else {
|
||||||
|
console.error("Unexpected error")
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Second member must be approved by first member
|
// Second member must be approved by first member
|
||||||
const vote2 = member2.initiateValidationPool(bench, {fee: 1, duration: 1000, tokenLossRatio: 1});
|
{
|
||||||
await member1.castVote(bench, vote2, true, 0.5, 1);
|
const pool = member2.initiateValidationPool(bench, {fee: 1, duration: 1000, tokenLossRatio: 1});
|
||||||
await member1.revealIdentity(bench, vote2); // Vote passes
|
await member1.castVote(pool, true, 0.5, 1);
|
||||||
|
await member1.revealIdentity(pool); // Vote passes
|
||||||
|
updateDisplayValues();
|
||||||
|
await delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
updateDisplayValues();
|
updateDisplayValues();
|
||||||
|
|
||||||
|
scene.deactivateAll();
|
||||||
|
|
Loading…
Reference in New Issue