Browse Source

council commitments

Joystream Stats 3 years ago
parent
commit
02baf92040

+ 0 - 2
server/api/members.ts

@@ -5,8 +5,6 @@ import {
   Proposal,
   Council,
   Consul,
-  ConsulStake,
-  ProposalVote,
 } from '../db/models'
 import donate from '../donate'
 

+ 7 - 5
server/db/models/councilstake.ts → server/db/models/commitment.ts

@@ -1,28 +1,30 @@
 import db from '../db'
 import { DataTypes } from 'sequelize'
 
-const Stake = db.define('consulstake', {
+const Commitment = db.define('commitment', {
+  round: DataTypes.INTEGER,
   stake: DataTypes.INTEGER,
+  vote: DataTypes.STRING
 })
 
-Stake.findAllWithIncludes = function () {
+Commitment.findAllWithIncludes = function () {
   return this.findAll({
     include: [{ model: db.models.consul }, { model: db.models.member }],
   })
 }
 
-Stake.findByIdWithIncludes = function (id: number, args?: { where: any }) {
+Commitment.findByIdWithIncludes = function (id: number, args?: { where: any }) {
   return this.findByPk(id, {
     ...args,
     include: [{ model: db.models.consul }, { model: db.models.member }],
   })
 }
 
-Stake.findWithIncludes = function (args: { where: any }) {
+Commitment.findWithIncludes = function (args: { where: any }) {
   return this.findAll({
     ...args,
     include: [{ model: db.models.consul }, { model: db.models.member }],
   })
 }
 
-export default Stake
+export default Commitment

+ 12 - 0
server/db/models/council.ts

@@ -18,6 +18,10 @@ Council.findAllWithIncludes = function () {
   return this.findAll({
     order,
     include: [
+      {
+        model: db.models.commitment,
+        include: [{ model: db.models.member, attributes: ['handle'] }],
+      },
       {
         model: db.models.consul,
         include: [
@@ -40,6 +44,10 @@ Council.findByIdWithIncludes = function (id: number, args?: { where: any }) {
   return this.findByPk(id, {
     ...args,
     include: [
+      {
+        model: db.models.commitment,
+        include: [{ model: db.models.member, attributes: ['handle'] }],
+      },
       {
         model: db.models.consul,
         include: [
@@ -63,6 +71,10 @@ Council.findWithIncludes = function (args?: { where: any }) {
     ...args,
     order,
     include: [
+      {
+        model: db.models.commitment,
+        include: [{ model: db.models.member, attributes: ['handle'] }],
+      },
       {
         model: db.models.consul,
         include: [

+ 7 - 6
server/db/models/index.ts

@@ -4,7 +4,7 @@ import Block from './block'
 import Channel from './channel'
 import Council from './council'
 import Consul from './councilseat'
-import ConsulStake from './councilstake'
+import Commitment from './commitment'
 import Era from './era'
 import Event from './event'
 import Proposal from './proposal'
@@ -20,7 +20,7 @@ Member.hasMany(Account)
 Member.belongsTo(Account, { as: 'root', constraints: false })
 Member.belongsTo(Account, { as: 'controller', constraints: false })
 Member.hasMany(Consul, { as: 'terms' })
-Member.hasMany(ConsulStake, { as: 'votes' })
+Member.hasMany(Commitment, { as: 'votes' })
 Member.hasMany(Category)
 Member.hasMany(Thread)
 Member.hasMany(Post)
@@ -44,12 +44,13 @@ Event.belongsTo(Block)
 
 Council.hasMany(Consul)
 Council.hasMany(Proposal)
+Council.hasMany(Commitment)
 Consul.belongsTo(Council)
 Consul.belongsTo(Member)
-Consul.hasMany(ConsulStake, { as: 'voters' })
+Consul.hasMany(Commitment, { as: 'voters' })
 Consul.hasMany(ProposalVote, { as: 'votes' })
-ConsulStake.belongsTo(Consul)
-ConsulStake.belongsTo(Member)
+Commitment.belongsTo(Consul)
+Commitment.belongsTo(Member)
 
 Channel.belongsTo(Member, { as: 'owner' })
 
@@ -89,7 +90,7 @@ export {
   Channel,
   Council,
   Consul,
-  ConsulStake,
+  Commitment,
   Era,
   Event,
   Member,

+ 1 - 1
server/db/seed.ts

@@ -6,7 +6,7 @@ import {
   Channel,
   Council,
   Consul,
-  ConsulStake,
+  Commitment,
   Member,
   Post,
   Proposal,

+ 97 - 34
server/joystream/index.ts

@@ -10,7 +10,7 @@ import {
   Channel,
   Council,
   Consul,
-  ConsulStake,
+  Commitment,
   Era,
   Event,
   Member,
@@ -25,6 +25,7 @@ import {
 // library
 import {
   getBlockHash,
+  getHead,
   getTimestamp,
   getEra,
   getEraStake,
@@ -34,6 +35,8 @@ import {
   getCouncilRound,
   getCouncilElectionStatus,
   getCouncilElectionDurations,
+  getCommitment,
+  getCommitments,
   getProposalCount,
   getProposal,
   getProposalVotes,
@@ -61,7 +64,7 @@ import moment from 'moment'
 import chalk from 'chalk'
 
 // types
-import { AccountBalance, Round, ProposalDetail } from './lib/types'
+import { AccountBalance, Round, Vote, ProposalDetail } from './lib/types'
 import {
   AccountId,
   BlockNumber,
@@ -72,7 +75,7 @@ import {
 } from '@polkadot/types/interfaces'
 import { HeaderExtended } from '@polkadot/api-derive/types'
 //import { AccountInfo } from '@polkadot/types/interfaces/system'
-import { Seat } from '@joystream/types/council'
+import { SealedVote, Seat } from '@joystream/types/council'
 import { MemberId, Membership } from '@joystream/types/members'
 import {
   ProposalId,
@@ -86,6 +89,7 @@ import {
   MemberType,
   CategoryType,
   ChannelType,
+  CommitmentType,
   PostType,
   ThreadType,
   CouncilType,
@@ -231,7 +235,7 @@ const updateStatus = async (
 }
 
 const fetchAll = async (api: ApiPromise, status: Status) => {
-  getCouncils(api, status.block).then((rounds: Round[]) =>
+  await getCouncils(api, status.block).then((rounds: Round[]) =>
     rounds.forEach((round) => fetchCouncil(api, round))
   )
   queue.push(() => fetchAccounts(api))
@@ -411,6 +415,7 @@ const createModeration = async (
   const key = accountId.toHuman()
   await Account.findOrCreate({ where: { key } })
   const where = { ...association, moderatorKey: key }
+  return // TODO
   const [moderation] = await Moderation.findOrCreate({ where })
   if (moderation) object.setModeration(moderation.id)
 }
@@ -454,50 +459,108 @@ const fetchThread = async (api: ApiPromise, id: number) => {
   return thread
 }
 
+// council
+interface Council {
+  round: number
+  start: number
+  startDate?: number
+  end: number
+  endDate?: number
+}
+
 const fetchCouncil = async (api: ApiPromise, term: Round) => {
   const { round, start, end } = term
   const exists = await Council.findByPk(round)
-  if (exists) return exists
+  //if (exists) return exists
   processing = `council ${round}`
+  let council: Council = { start, end, round }
   const startHash = await getBlockHash(api, start)
-  const startDate = await getTimestamp(api, startHash)
+  council.startDate = await getTimestamp(api, startHash)
   const seats: Seat[] = await getCouncil(api, startHash)
-  let council: { [key: string]: number | string } = {
-    start,
-    end,
-    round,
-    startDate,
-  }
-  try {
+  const head = Number(await getHead(api))
+  if (end < head) {
     const endHash = await getBlockHash(api, end)
     if (endHash) council.endDate = await getTimestamp(api, endHash)
-  } catch (e) {}
+  } else console.log(`fetchCouncil: round ${round} is ongoing.`)
+
   // TODO import report generator and save tokenomics
-  Council.create(council)
-    .then(({ round }: any) =>
-      seats.map(({ member, stake, backers }) =>
-        fetchMemberByAccount(api, member).then(({ id }: any) =>
-          Consul.create({
-            stake: Number(stake),
-            councilRound: round,
-            memberId: id,
-          }).then((consul: any) =>
-            backers.map(async ({ member, stake }) =>
-              fetchMemberByAccount(api, member).then(({ id }: any) =>
-                ConsulStake.create({
-                  stake: Number(stake),
-                  consulId: consul.id,
-                  memberId: id,
-                })
-              )
-            )
-          )
+  saveCouncil(api, council, seats)
+  saveCommitments(api, round, start - 2)
+}
+
+const saveCommitments = async (
+  api: ApiPromise,
+  round: number,
+  block: number
+) => {
+  console.log(round, block)
+  const hash = await getBlockHash(api, block)
+  const commitments: Hash[] = await getCommitments(api, hash)
+  Promise.all(
+    commitments.map((voteHash: Hash) => getCommitment(api, hash, voteHash))
+  ).then((votes: SealedVote[]) =>
+    votes.map(async (v) => {
+      const voter: AccountId = v.voter
+      const stake = v.stake.new.toNumber()
+      const vote = String(v.vote)
+      const member = await fetchMemberByAccount(api, voter)
+      const memberId = member?.id
+      Commitment.findOrCreate({
+        where: { councilRound: round, stake, memberId },
+      }).then(([c]: [CommitmentType]) => vote && c.update({ vote }))
+    })
+  )
+}
+
+const saveCouncil = async (
+  api: ApiPromise,
+  council: Council,
+  seats: Seat[]
+) => {
+  const { round } = council
+  //console.log(`council`, council)
+  Council.findOrCreate({ where: { round } })
+    .then(([council]: [CouncilType]) => {
+      council.update(council)
+      seats.map((seat) =>
+        fetchMemberByAccount(api, seat.member).then(
+          (member: MemberType | undefined) =>
+            member && saveConsul(api, round, member.id, seat)
         )
       )
-    )
+    })
     .catch((e: any) => console.error(`Failed to save council ${round}`, e))
 }
 
+const saveConsul = async (
+  api: ApiPromise,
+  councilRound: number,
+  memberId: number,
+  seat?: Seat
+) =>
+  Consul.findOrCreate({ where: { councilRound, memberId } }).then(
+    ([consul]: any) => {
+      if (!seat) return
+      const stake = Number(seat.stake)
+      consul.update({ stake })
+      seat.backers.map(async ({ member, stake }) =>
+        fetchMemberByAccount(api, member).then(({ id }: any) =>
+          saveCommitment(Number(stake), consul.id, id)
+        )
+      )
+    }
+  )
+
+const saveCommitment = async (
+  stake: number,
+  consulId: number,
+  memberId: number,
+  vote?: string
+) =>
+  Commitment.findOrCreate({ where: { stake, consulId, memberId } }).then(
+    ([c]: [CommitmentType]) => vote && c.update({ vote })
+  )
+
 const fetchProposal = async (api: ApiPromise, id: number) => {
   if (id <= 0) return
   queue.push(() => fetchProposal(api, id - 1))

+ 1 - 1
server/joystream/lib

@@ -1 +1 @@
-Subproject commit 5b72c51293bd91b4ed3e7e6cb876c56bbba00ef0
+Subproject commit b88d26ce5ae28b36d3402fb778a1efc4c2fee223