diff --git a/forum-network/.eslintrc.js b/forum-network/.eslintrc.js
index 3a4f0e3..6f3bea1 100644
--- a/forum-network/.eslintrc.js
+++ b/forum-network/.eslintrc.js
@@ -37,6 +37,7 @@ module.exports = {
'no-multi-assign': ['off'],
'no-constant-condition': ['off'],
'no-await-in-loop': ['off'],
+ 'no-underscore-dangle': ['off'],
},
globals: {
_: 'readonly',
@@ -44,5 +45,6 @@ module.exports = {
sinon: 'readonly',
sinonChai: 'readonly',
should: 'readonly',
+ mocha: 'readonly',
},
};
diff --git a/forum-network/notes/business.md b/forum-network/notes/business.md
new file mode 100644
index 0000000..ff50bde
--- /dev/null
+++ b/forum-network/notes/business.md
@@ -0,0 +1,101 @@
+# Revenue-generating work
+
+## Expert stakes REP to register availability
+
+```mermaid
+graph
+
+subgraph EOA
+ expert(Expert)
+
+end
+
+subgraph Contracts
+ availability(Availability)
+end
+
+expert -- 1. Stake ℝ --> availability
+
+```
+
+## Public submits work request with fee
+
+```mermaid
+graph
+
+subgraph EOA
+ expert(Expert)
+ public(Public)
+end
+
+subgraph Contracts
+ business(Business)
+ availability(Availability)
+end
+
+public -- 1. Request
with fee $ --> business
+business -- 2. Assign
work --> availability
+availability -- 3. Transfer
staked ℝ --> business
+availability -- 4. TODO Notify --> expert
+```
+
+## Expert submits work evidence
+
+```mermaid
+graph
+
+subgraph EOA
+ expert(Expert)
+end
+
+subgraph Contracts
+ business(Business)
+ forum(Forum)
+ pool(Pool)
+end
+
+expert -- 1. Work
evidence --> business
+business -- 2. Post --> forum
+business -- 3. Stake ℝ --> pool
+```
+
+## Peers validate the work evidence
+
+```mermaid
+graph
+
+subgraph EOA
+ peers(Peers)
+end
+
+subgraph Contracts
+ forum(Forum)
+ pool(Pool)
+end
+
+peers -- 8. Stake ℝ --> pool
+pool -- 9. Validate post,
Transfer ℝ --> forum
+```
+
+## Rewards are distributed
+
+```mermaid
+graph
+
+subgraph EOA
+ expert(Expert)
+ peers(Peers)
+end
+
+subgraph Contracts
+ pool(Pool)
+ business(Business)
+ forum(Forum)
+end
+
+pool -- Reward ℝ --> peers
+forum -- Award ℝ --> expert
+forum -- Award ℝ
via citation
WDAG --> peers
+business -- Award % fee $
weighted by ℝ--> expert
+business -- Award % fee $
weighted by ℝ--> peers
+```
diff --git a/forum-network/notes/classes.md b/forum-network/notes/classes.md
deleted file mode 100644
index 36cb19d..0000000
--- a/forum-network/notes/classes.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# Primary
-
-## Forum
-
-## ValidationPool
-
-## ReputationToken
-
-## WDAG
-
-# Secondary
-
-## Availability
-
-## Business
-
-## ERC721
-
-## Expert
-
-## Bench
-
-# Tertiary
-
-## Actor
-
-## Action
-
-## Scene
-
-# To Explore
-
-## Exchange
-
-## Storage
-
-## Network
-
-## Wallet
-
-## Agent/UI
-
-## BlockConsensus
diff --git a/forum-network/notes/client-or-ui.md b/forum-network/notes/client-or-ui.md
new file mode 100644
index 0000000..ad24afd
--- /dev/null
+++ b/forum-network/notes/client-or-ui.md
@@ -0,0 +1,9 @@
+## Client/UI
+
+Voting consists of staking operations performed by software operated by owners of EOA.
+
+This software may be referred to as "The UI". It may also be considered "a client".
+
+It will need to be a network-connected application. It will need a certain minimum of RAM,
+and for some features disk storage,
+and for some features uptime .
diff --git a/forum-network/notes/client.md b/forum-network/notes/client.md
new file mode 100644
index 0000000..55df288
--- /dev/null
+++ b/forum-network/notes/client.md
@@ -0,0 +1,5 @@
+# Client Operations
+
+Client must communicate with one or more servers.
+
+Client must build a local view
diff --git a/forum-network/notes/dao.md b/forum-network/notes/dao.md
index 58f017a..048efbf 100644
--- a/forum-network/notes/dao.md
+++ b/forum-network/notes/dao.md
@@ -33,3 +33,114 @@ WHAT is our protocol for evaluating the perspectives offered by peers?
- If there is the HOPE of exact agreement, mistakes and attacks can be costly
- If there is an EXPECTATION of exact agreement, there must be externalities supporting that agreement, i.e. a common protocol and governance of that protocol.
+
+---
+
+# Internal operations
+
+## Expert starts new DAO
+
+```mermaid
+graph
+
+subgraph EOA
+ expert(Expert)
+end
+
+subgraph Contracts
+ forum(Forum)
+ pool(Pool)
+end
+
+expert -- Post --> forum
+expert -- Fee $ --> pool
+
+```
+
+## Expert joins existing DAO
+
+```mermaid
+graph
+
+subgraph EOA
+ expert(Expert)
+ peers(Peers)
+end
+
+subgraph Contracts
+ forum(Forum)
+ pool(Pool)
+end
+
+expert -- 1. Post --> forum
+expert -- 2. Fee $ --> pool
+peers -- 3. Stake ℝ
to approve --> pool
+```
+
+## Expert submits governance post
+
+A governance post can be considered one that is respected in some way by the operations of the [Client/UI](./client-or-ui.md).
+
+This is a broad class of posts.
+
+Each type of governance post can be individually (or by category?) handled by the business contract for a given DAO.
+
+```mermaid
+graph
+
+subgraph EOA
+ expert(Expert)
+ peers(Peers)
+end
+
+subgraph Contracts
+ forum(Forum)
+ pool(Pool)
+ business(Business)
+end
+
+expert -- 1. Stake ℝ on
governance post --> business
+business -- 2. Post --> forum
+business -- 2. Fee $ from
internal fund? --> pool
+peers -- 3. Stake ℝ
to approve --> pool
+pool -- 4. Validate --> forum
+```
+
+Forum usage is open-ended.
+DAO protocol consists of core contracts + client behaviors.
+Core contracts provide resilience to attacks, since reputation minting is financially backed by future income
+
+Question: What does the DAO do with funds it receives?
+Awswer: Distributes the funds to members immediately upon resolution of the reputation effects of a funded validation pool.
+
+---
+
+Before we delve into example use cases, we need to talk about the [Client/UI](./client-or-ui.md), and make sure we have
+a sound understanding of how client/ui behaviors interact with the core of the system.
+
+---
+
+The forum, pool, business, and availability contracts all work together to express a single DAO.
+
+Each post in the forum can be its own new DAO
+
+What it would take for that to happen:
+
+The seed of the new DAO becomes the tokens minted by that post DAO when it receives fees.
+
+When will it receive fees? When submitted to its business contract interface.
+
+What happens then? Work is assigned via availability stakes.
+
+Meaning that someone has staked reputation.
+
+Meaning that they had previously been awarded reputation.
+
+The business contract, or the DAO, or the seed post, must be able to accept an initial fee
+to mint the reputation of the first expert.
+
+Then, that expert can stake their reputation on availability to perform the work expressed by the post and its associated business contract.
+
+These operations can be consolidated.
+
+When submitting a post to the forum, you may include an optional fee
diff --git a/forum-network/notes/governance.md b/forum-network/notes/governance.md
new file mode 100644
index 0000000..74dd787
--- /dev/null
+++ b/forum-network/notes/governance.md
@@ -0,0 +1 @@
+Each DAO needs to allocate some of its incoming fees to incentivize development.
diff --git a/forum-network/notes/rooms.md b/forum-network/notes/rooms.md
new file mode 100644
index 0000000..4674fa2
--- /dev/null
+++ b/forum-network/notes/rooms.md
@@ -0,0 +1,30 @@
+Matrix uses rooms to establish contexts.
+
+We can have a forum context,
+wherein a few things happen.
+
+One is that the forum will have a root post; equivalently, any post can be the root of a forum.
+
+The context of that post can be preserved.
+
+The forum is thus a collection of posts. Each post MAY have its own internal structure.
+A post MAY "replace" a prior post. This consists of on-chain and off-chain elements.
+On-chain, a new post replaces a prior post.
+
+---
+
+Reading Matrix spec, https://spec.matrix.org/latest/
+
+> Events are signed by the originating server (the signature includes the parent relations, type, depth and payload hash) and are pushed over federation to the participating servers in a room, currently using full mesh topology. Servers may also request backfill of events over federation from the other servers participating in a room.
+
+> In order to ensure that the mapping from 3PID to user ID is genuine, a globally federated cluster of trusted “identity servers” (IS) are used to verify the 3PID and persist and replicate the mappings.
+>
+> Usage of an IS is not required in order for a client application to be part of the Matrix ecosystem. However, without one clients will not be able to look up user IDs using 3PIDs.
+
+> Users may publish arbitrary key/value data associated with their account
+>
+> - such as a human-readable display name, a profile photo URL, contact information (email address, phone numbers, website URLs etc).
+
+> Users may also store arbitrary private key/value data in their account - such as client preferences, or server configuration settings which lack any other dedicated API. The API is symmetrical to managing Profile data.
+
+> The client-server API allows clients to send messages, control rooms and synchronise conversation history. It is designed to support both lightweight clients which store no state and lazy-load data from the server as required - as well as heavyweight clients which maintain a full local persistent copy of server state.
diff --git a/forum-network/notes/system.gv b/forum-network/notes/system.gv
new file mode 100644
index 0000000..e3a4a59
--- /dev/null
+++ b/forum-network/notes/system.gv
@@ -0,0 +1,4 @@
+digraph {
+ layout=neato
+
+}
diff --git a/forum-network/notes/system.md b/forum-network/notes/system.md
new file mode 100644
index 0000000..d19418c
--- /dev/null
+++ b/forum-network/notes/system.md
@@ -0,0 +1,56 @@
+```mermaid
+graph
+ classDef blue fill:#08f, color:#d8d8d8, stroke-width: 0
+ classDef yellow fill:#dd0, color:#a0c, stroke-width: 0
+ classDef green fill:#8c8, color:#333, stroke-width: 0
+ classDef purple stroke:#c38, stroke-width:2px, fill:#bbf, color:#c38
+ classDef orange fill:#d60, color:#dff, stroke-width: 0
+ classDef fuscia fill:#f6c, color:#00c
+
+ nodeSpec(Node spec
Matrix homeservers):::blue
+ storageSpec(Storage spec
Matrix homeservers):::orange
+ archiveSpec(Archive spec
Weavechain):::green
+ blockchainSpec(Blockchain spec):::purple
+ peerProtocolSpec(Peer protocol spec
Matrix messaging):::yellow
+ uiSpec(UI spec
Matrix client):::fuscia
+
+
+ nodeSpec --- uiSpec
+ linkStyle 0 stroke:#08f
+ nodeSpec --- storageSpec
+ linkStyle 1 stroke:#08f
+ nodeSpec --- peerProtocolSpec
+ linkStyle 2 stroke:#08f
+ nodeSpec --- archiveSpec
+ linkStyle 3 stroke:#08f
+ nodeSpec --- blockchainSpec
+ linkStyle 4 stroke:#08f
+
+ peerProtocolSpec --- storageSpec
+ linkStyle 5 stroke:#d60
+
+ storageSpec --- blockchainSpec
+ linkStyle 6 stroke:#c38
+ storageSpec --- archiveSpec
+ linkStyle 7 stroke:#8c8
+
+ archiveSpec --- blockchainSpec
+ linkStyle 8 stroke:#c38
+
+ uiSpec --- blockchainSpec
+ linkStyle 9 stroke:#c38
+ uiSpec --- archiveSpec
+ linkStyle 10 stroke:#8c8
+ uiSpec --- storageSpec
+ linkStyle 11 stroke:#d60
+```
+
+```mermaid
+graph
+
+forum --- pool
+availability --- business
+business --- forum
+business --- pool
+
+```
diff --git a/forum-network/src/classes/actors/expert.js b/forum-network/src/classes/actors/expert.js
index b8ecda0..69a1d7c 100644
--- a/forum-network/src/classes/actors/expert.js
+++ b/forum-network/src/classes/actors/expert.js
@@ -1,7 +1,7 @@
import { Action } from '../display/action.js';
import { PostMessage } from '../forum-network/message.js';
import { CryptoUtil } from '../util/crypto.js';
-import { ReputationHolder } from './reputation-holder.js';
+import { ReputationHolder } from '../reputation/reputation-holder.js';
export class Expert extends ReputationHolder {
constructor(dao, name, scene) {
@@ -47,7 +47,7 @@ export class Expert extends ReputationHolder {
}
async initiateValidationPool(poolOptions) {
- // For now, directly call bench.initiateValidationPool();
+ // For now, make direct call rather than network
poolOptions.reputationPublicKey = this.reputationPublicKey;
const pool = await this.dao.initiateValidationPool(poolOptions);
this.tokens.push(pool.tokenId);
diff --git a/forum-network/src/classes/actors/post.js b/forum-network/src/classes/actors/post.js
deleted file mode 100644
index a214c6d..0000000
--- a/forum-network/src/classes/actors/post.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import { Actor } from '../display/actor.js';
-import { displayNumber } from '../../util.js';
-import params from '../../params.js';
-
-export class Post extends Actor {
- constructor(forum, authorPublicKey, postContent) {
- const index = forum.posts.countVertices();
- const name = `Post${index + 1}`;
- super(name, forum.scene);
- this.id = postContent.id ?? name;
- this.authorPublicKey = authorPublicKey;
- this.value = 0;
- this.initialValue = 0;
- this.citations = postContent.citations;
- this.title = postContent.title;
- const leachingTotal = this.citations
- .filter(({ weight }) => weight < 0)
- .reduce((total, { weight }) => total += -weight, 0);
- const donationTotal = this.citations
- .filter(({ weight }) => weight > 0)
- .reduce((total, { weight }) => total += weight, 0);
- if (leachingTotal > params.revaluationLimit) {
- throw new Error('Post leaching total exceeds revaluation limit '
- + `(${leachingTotal} > ${params.revaluationLimit})`);
- }
- if (donationTotal > params.revaluationLimit) {
- throw new Error('Post donation total exceeds revaluation limit '
- + `(${donationTotal} > ${params.revaluationLimit})`);
- }
- if (this.citations.some(({ weight }) => Math.abs(weight) > params.revaluationLimit)) {
- throw new Error(`Each citation magnitude must not exceed revaluation limit ${params.revaluationLimit}`);
- }
- }
-
- getLabel() {
- return `${this.name}
-
- initial |
- ${displayNumber(this.initialValue)} |
-
- value |
- ${displayNumber(this.value)} |
-
`
- .replaceAll(/\n\s*/g, '');
- }
-}
diff --git a/forum-network/src/classes/actors/availability.js b/forum-network/src/classes/dao/availability.js
similarity index 100%
rename from forum-network/src/classes/actors/availability.js
rename to forum-network/src/classes/dao/availability.js
diff --git a/forum-network/src/classes/actors/business.js b/forum-network/src/classes/dao/business.js
similarity index 100%
rename from forum-network/src/classes/actors/business.js
rename to forum-network/src/classes/dao/business.js
diff --git a/forum-network/src/classes/actors/dao.js b/forum-network/src/classes/dao/dao.js
similarity index 90%
rename from forum-network/src/classes/actors/dao.js
rename to forum-network/src/classes/dao/dao.js
index ee6f6a3..938d019 100644
--- a/forum-network/src/classes/actors/dao.js
+++ b/forum-network/src/classes/dao/dao.js
@@ -1,6 +1,6 @@
import params from '../../params.js';
import { Forum } from './forum.js';
-import { ReputationTokenContract } from '../contracts/reputation-token.js';
+import { ReputationTokenContract } from '../reputation/reputation-token.js';
import { ValidationPool } from './validation-pool.js';
import { Availability } from './availability.js';
import { Business } from './business.js';
@@ -72,9 +72,4 @@ export class DAO extends Actor {
return pool;
}
-
- async submitPost(reputationPublicKey, postContent) {
- const post = await this.forum.addPost(reputationPublicKey, postContent);
- return post.id;
- }
}
diff --git a/forum-network/src/classes/actors/forum.js b/forum-network/src/classes/dao/forum.js
similarity index 79%
rename from forum-network/src/classes/actors/forum.js
rename to forum-network/src/classes/dao/forum.js
index 41ae511..6a6db0f 100644
--- a/forum-network/src/classes/actors/forum.js
+++ b/forum-network/src/classes/dao/forum.js
@@ -1,13 +1,56 @@
import { WDAG } from '../supporting/wdag.js';
import { Action } from '../display/action.js';
+import { Actor } from '../display/actor.js';
import params from '../../params.js';
-import { ReputationHolder } from './reputation-holder.js';
+import { ReputationHolder } from '../reputation/reputation-holder.js';
import { displayNumber, EPSILON } from '../../util.js';
-import { Post } from './post.js';
const CITATION = 'citation';
const BALANCE = 'balance';
+class Post extends Actor {
+ constructor(forum, authorPublicKey, postContent) {
+ const index = forum.posts.countVertices();
+ const name = `Post${index + 1}`;
+ super(name, forum.scene);
+ this.id = postContent.id ?? name;
+ this.authorPublicKey = authorPublicKey;
+ this.value = 0;
+ this.initialValue = 0;
+ this.citations = postContent.citations;
+ this.title = postContent.title;
+ const leachingTotal = this.citations
+ .filter(({ weight }) => weight < 0)
+ .reduce((total, { weight }) => total += -weight, 0);
+ const donationTotal = this.citations
+ .filter(({ weight }) => weight > 0)
+ .reduce((total, { weight }) => total += weight, 0);
+ if (leachingTotal > params.revaluationLimit) {
+ throw new Error('Post leaching total exceeds revaluation limit '
+ + `(${leachingTotal} > ${params.revaluationLimit})`);
+ }
+ if (donationTotal > params.revaluationLimit) {
+ throw new Error('Post donation total exceeds revaluation limit '
+ + `(${donationTotal} > ${params.revaluationLimit})`);
+ }
+ if (this.citations.some(({ weight }) => Math.abs(weight) > params.revaluationLimit)) {
+ throw new Error(`Each citation magnitude must not exceed revaluation limit ${params.revaluationLimit}`);
+ }
+ }
+
+ getLabel() {
+ return `${this.name}
+
+ initial |
+ ${displayNumber(this.initialValue)} |
+
+ value |
+ ${displayNumber(this.value)} |
+
`
+ .replaceAll(/\n\s*/g, '');
+ }
+}
+
/**
* Purpose:
* - Forum: Maintain a directed, acyclic, graph of positively and negatively weighted citations.
diff --git a/forum-network/src/classes/actors/validation-pool.js b/forum-network/src/classes/dao/validation-pool.js
similarity index 99%
rename from forum-network/src/classes/actors/validation-pool.js
rename to forum-network/src/classes/dao/validation-pool.js
index 5accbf6..4781608 100644
--- a/forum-network/src/classes/actors/validation-pool.js
+++ b/forum-network/src/classes/dao/validation-pool.js
@@ -1,4 +1,4 @@
-import { ReputationHolder } from './reputation-holder.js';
+import { ReputationHolder } from '../reputation/reputation-holder.js';
import { Stake } from '../supporting/stake.js';
import { Voter } from '../supporting/voter.js';
import params from '../../params.js';
diff --git a/forum-network/src/classes/display/action.js b/forum-network/src/classes/display/action.js
index 9c1329e..3a2e24c 100644
--- a/forum-network/src/classes/display/action.js
+++ b/forum-network/src/classes/display/action.js
@@ -4,6 +4,15 @@ export class Action {
this.scene = scene;
}
+ /**
+ *
+ * @param src
+ * @param dest
+ * @param msg
+ * @param obj
+ * @param symbol
+ * @returns {Promise}
+ */
async log(src, dest, msg, obj, symbol = '->>') {
await this.scene?.sequence?.log(
`${src.name} ${symbol} ${dest.name} : ${this.name} ${msg ?? ''} ${
diff --git a/forum-network/src/classes/display/box.js b/forum-network/src/classes/display/box.js
index faacf17..46f49f6 100644
--- a/forum-network/src/classes/display/box.js
+++ b/forum-network/src/classes/display/box.js
@@ -2,16 +2,20 @@ import { DisplayValue } from './display-value.js';
import { randomID } from '../../util.js';
export class Box {
- constructor(name, parentEl, elementType = 'div') {
+ constructor(name, parentEl, options = {}) {
this.name = name;
- this.el = document.createElement(elementType);
+ this.el = document.createElement('div');
this.el.id = `box_${randomID()}`;
this.el.classList.add('box');
if (name) {
this.el.setAttribute('box-name', name);
}
if (parentEl) {
- parentEl.appendChild(this.el);
+ if (options.prepend) {
+ parentEl.prepend(this.el);
+ } else {
+ parentEl.appendChild(this.el);
+ }
}
}
@@ -35,8 +39,8 @@ export class Box {
return this;
}
- addBox(name, elementType) {
- const box = new Box(name, this.el, elementType);
+ addBox(name) {
+ const box = new Box(name, this.el);
return box;
}
diff --git a/forum-network/src/classes/display/controls.js b/forum-network/src/classes/display/controls.js
new file mode 100644
index 0000000..4911456
--- /dev/null
+++ b/forum-network/src/classes/display/controls.js
@@ -0,0 +1,52 @@
+class Button {
+ constructor(innerHTML, onclick) {
+ this.el = document.createElement('button');
+ this.el.innerHTML = innerHTML;
+ this.el.onclick = onclick;
+ }
+}
+
+export class Controls {
+ constructor(parentBox) {
+ this.disableAutoplayButton = new Button('Disable Auto-play', () => {
+ const url = new URL(window.location.href);
+ url.searchParams.set('auto', 'false');
+ window.location.href = url.href;
+ });
+ this.enableAutoplayButton = new Button('Enable Auto-play', () => {
+ const url = new URL(window.location.href);
+ url.searchParams.delete('auto');
+ window.location.href = url.href;
+ });
+ this.stepButton = new Button('Next Action', () => {
+ console.log('Next Action button clicked');
+ document.dispatchEvent(new Event('next-action'));
+ });
+
+ if (window.autoPlay) {
+ parentBox.el.appendChild(this.disableAutoplayButton.el);
+ } else {
+ parentBox.el.appendChild(this.enableAutoplayButton.el);
+ parentBox.el.appendChild(this.stepButton.el);
+ // Disable `stepButton` when test is complete
+ setInterval(() => {
+ this.stepButton.el.disabled = mocha._state !== 'running';
+ }, 200);
+ }
+ }
+}
+
+export async function delayOrWait(delayMs) {
+ if (window.autoPlay) {
+ await new Promise((resolve) => {
+ setTimeout(resolve, delayMs);
+ });
+ } else {
+ await new Promise((resolve) => {
+ document.addEventListener('next-action', () => {
+ console.log('next-action event received');
+ resolve();
+ }, { once: true });
+ });
+ }
+}
diff --git a/forum-network/src/classes/display/scene.js b/forum-network/src/classes/display/scene.js
index e455421..f0e76b3 100644
--- a/forum-network/src/classes/display/scene.js
+++ b/forum-network/src/classes/display/scene.js
@@ -4,6 +4,8 @@ import { MermaidDiagram } from './mermaid.js';
import { SequenceDiagram } from './sequence.js';
import { Table } from './table.js';
import { Flowchart } from './flowchart.js';
+import { Controls } from './controls.js';
+import { Box } from './box.js';
export class Scene {
constructor(name, rootBox) {
@@ -24,6 +26,14 @@ export class Scene {
this.options = {
edgeNodeColor: '#4d585c',
};
+
+ window.autoPlay = new URL(window.location.href).searchParams.get('auto') !== 'false';
+
+ if (!window.disableSceneControls) {
+ this.topRail = new Box('Top rail', document.body, { prepend: true }).addClass('top-rail');
+ this.controlsBox = this.topRail.addBox('Controls').addClass('controls');
+ this.controls = new Controls(this.controlsBox);
+ }
}
withSequenceDiagram() {
diff --git a/forum-network/src/classes/display/table.js b/forum-network/src/classes/display/table.js
index 10dbd0b..ee579d4 100644
--- a/forum-network/src/classes/display/table.js
+++ b/forum-network/src/classes/display/table.js
@@ -42,4 +42,8 @@ export class Table {
cell.innerHTML = typeof value === 'number' ? displayNumber(value) : value ?? '';
}
}
+
+ listUniqueValueKeys() {
+ return this.columns; // TODO
+ }
}
diff --git a/forum-network/src/classes/forum-network/forum-node.js b/forum-network/src/classes/forum-network/forum-node.js
index f36032e..49ae7c5 100644
--- a/forum-network/src/classes/forum-network/forum-node.js
+++ b/forum-network/src/classes/forum-network/forum-node.js
@@ -4,7 +4,7 @@ import {
} from './message.js';
import { ForumView } from './forum-view.js';
import { NetworkNode } from './network-node.js';
-import { randomID } from '../../util.js';
+import { randomID } from '../util/util.js';
export class ForumNode extends NetworkNode {
constructor(name, scene) {
diff --git a/forum-network/src/classes/ideas/exchange.js b/forum-network/src/classes/ideas/exchange.js
index e69de29..2c1021f 100644
--- a/forum-network/src/classes/ideas/exchange.js
+++ b/forum-network/src/classes/ideas/exchange.js
@@ -0,0 +1,45 @@
+import { DAO } from '../actors/dao.js';
+/**
+ * An Exchange provides conversion between currencies / facilitates such.
+ * That means they carry some of the risk of managing these transactions.
+ *
+ */
+
+class Offer {
+ constructor({
+ _fromType, _toType, _amount, price,
+ }) {
+ this.price = price;
+ // const from =
+ }
+}
+
+export class Exchange extends DAO {
+ constructor(name, scene) {
+ super(name, scene);
+ this.offersByType = new Map(); // >
+ }
+
+ getOffers(offerType) {
+ return this.buyOffersByType.get(offerType) ?? new Map(); // <
+ }
+
+ addOffer(offerOptions) {
+ const offer = new Offer(offerOptions);
+ const { fromType, toType } = offer;
+ [fromType, toType].forEach((type) => {
+ this.offersByType.s();
+ });
+ }
+
+ requestTransaction({
+ fromType, toType, amount, price,
+ }) {
+ // this.
+ }
+
+ buy(fromType, toType, _priceParameters) {
+ const buyOffer = {
+ };
+ }
+}
diff --git a/forum-network/src/classes/ideas/finance.js b/forum-network/src/classes/ideas/finance.js
index 0ca5f53..07e7531 100644
--- a/forum-network/src/classes/ideas/finance.js
+++ b/forum-network/src/classes/ideas/finance.js
@@ -1,10 +1,6 @@
-export class Token {
- constructor(ownerPublicKey) {
- this.ownerPublicKey = ownerPublicKey;
- }
+/**
+ * Finance does the work of analysis of the dynamics of reputation and currency exchange
+ */
- transfer(newOwnerPublicKey) {
- // TODO: Current owner must sign this request
- this.ownerPublicKey = newOwnerPublicKey;
- }
+export class Finance {
}
diff --git a/forum-network/src/classes/ideas/storage.js b/forum-network/src/classes/ideas/storage.js
index e69de29..e317264 100644
--- a/forum-network/src/classes/ideas/storage.js
+++ b/forum-network/src/classes/ideas/storage.js
@@ -0,0 +1,24 @@
+import { randomID } from '../util/util.js';
+
+class Pledge {
+ constructor({ stake, duration }) {
+ this.stake = stake;
+ this.duration = duration;
+ }
+}
+
+/**
+ * Storage work is providing data availability and integrity.
+ * It probably makes sense to manage it in pledges of finite duration.
+ */
+export class Storage {
+ constructor() {
+ this.pledges = new Map();
+ }
+
+ pledge(pledgeOptions) {
+ const id = randomID();
+ this.pledge.set(id, new Pledge(pledgeOptions));
+ return id;
+ }
+}
diff --git a/forum-network/src/classes/actors/reputation-holder.js b/forum-network/src/classes/reputation/reputation-holder.js
similarity index 100%
rename from forum-network/src/classes/actors/reputation-holder.js
rename to forum-network/src/classes/reputation/reputation-holder.js
diff --git a/forum-network/src/classes/contracts/reputation-token.js b/forum-network/src/classes/reputation/reputation-token.js
similarity index 94%
rename from forum-network/src/classes/contracts/reputation-token.js
rename to forum-network/src/classes/reputation/reputation-token.js
index c39af4d..6a479e1 100644
--- a/forum-network/src/classes/contracts/reputation-token.js
+++ b/forum-network/src/classes/reputation/reputation-token.js
@@ -1,4 +1,4 @@
-import { ERC721 } from './erc721.js';
+import { ERC721 } from '../supporting/erc721.js';
import { EPSILON, randomID } from '../../util.js';
@@ -19,7 +19,14 @@ export class ReputationTokenContract extends ERC721 {
this.locks = new Set(); // {tokenId, amount, start, duration}
}
- mint(to, value, context) {
+ /**
+ *
+ * @param to
+ * @param value
+ * @param context
+ * @returns {string}
+ */
+ mint(to, value, context = {}) {
const tokenId = `token_${randomID()}`;
super.mint(to, tokenId);
this.values.set(tokenId, value);
diff --git a/forum-network/src/classes/contracts/erc20.js b/forum-network/src/classes/supporting/erc20.js
similarity index 100%
rename from forum-network/src/classes/contracts/erc20.js
rename to forum-network/src/classes/supporting/erc20.js
diff --git a/forum-network/src/classes/contracts/erc721.js b/forum-network/src/classes/supporting/erc721.js
similarity index 100%
rename from forum-network/src/classes/contracts/erc721.js
rename to forum-network/src/classes/supporting/erc721.js
diff --git a/forum-network/src/index.css b/forum-network/src/index.css
index 1c71ee9..1ff9007 100644
--- a/forum-network/src/index.css
+++ b/forum-network/src/index.css
@@ -36,6 +36,17 @@ a:visited {
.padded {
padding: 20px;
}
+.top-rail {
+ position: sticky;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 0;
+}
+.controls {
+ position: relative;
+ left: 150px;
+}
svg {
width: 800px;
}
@@ -49,3 +60,14 @@ td {
.edge > rect {
fill: #216262 !important;
}
+button {
+ margin: 5px;
+ margin-top: 1em;
+ background-color: #c6f4ff;
+ border-color: #b6b6b6;
+ border-radius: 5px;
+}
+button:disabled {
+ background-color: #2a535e;
+ color: #919191;
+}
diff --git a/forum-network/src/tests/all.test.html b/forum-network/src/tests/all.test.html
index 82baba7..7f89e7c 100644
--- a/forum-network/src/tests/all.test.html
+++ b/forum-network/src/tests/all.test.html
@@ -12,6 +12,9 @@