Explorar el Código

query node - council & referendum mappings VIII

ondratra hace 3 años
padre
commit
afe96e8240

+ 66 - 62
query-node/mappings/council.ts

@@ -1,5 +1,5 @@
 import { EventContext, StoreContext, DatabaseManager } from '@dzlzv/hydra-common'
-import { bytesToString, deserializeMetadata, genericEventFields } from './common'
+import { deserializeMetadata, genericEventFields } from './common'
 import BN from 'bn.js'
 import { FindConditions } from 'typeorm'
 
@@ -35,7 +35,6 @@ import {
   ReferendumStageRevealingOptionResult,
 
   // Council & referendum schema types
-  ElectionProblemNotEnoughCandidates,
   CouncilStageUpdate,
   CouncilStageAnnouncing,
   CouncilStage,
@@ -54,6 +53,7 @@ import {
 } from 'query-node/dist/model'
 import { Council, Referendum } from './generated/types'
 import { CouncilCandidacyNoteMetadata } from '@joystream/metadata-protobuf'
+import { isSet } from '@joystream/metadata-protobuf/utils'
 
 /////////////////// Common - Gets //////////////////////////////////////////////
 
@@ -200,25 +200,21 @@ async function updateCouncilStage(
   store: DatabaseManager,
   councilStage: typeof CouncilStage,
   blockNumber: number,
-  electionProblem?: typeof ElectionProblem
+  electionProblem?: ElectionProblem
 ): Promise<void> {
+  const electedCouncil = await getCurrentElectedCouncil(store, true)
+  if (!electedCouncil) {
+    return
+  }
+
   const councilStageUpdate = new CouncilStageUpdate({
     stage: councilStage,
     changedAt: new BN(blockNumber),
-    electionProblem: electionProblem || new VariantNone(),
+    electionProblem,
+    electedCouncil,
   })
 
   await store.save<CouncilStageUpdate>(councilStageUpdate)
-
-  // update council record
-  const electedCouncil = await getCurrentElectedCouncil(store, true)
-  if (!electedCouncil) {
-    return
-  }
-
-  // electedCouncil.updates.push(councilStageUpdate) // uncomment after solving https://github.com/Joystream/hydra/issues/462
-  electedCouncil.updates = (electedCouncil.updates || []).concat([councilStageUpdate])
-  await store.save<ElectedCouncil>(electedCouncil)
 }
 
 /*
@@ -329,7 +325,7 @@ export async function council_NotEnoughCandidates({ event, store }: EventContext
   const stage = new CouncilStageAnnouncing()
   stage.candidatesCount = new BN(0)
 
-  await updateCouncilStage(store, stage, event.blockNumber, new ElectionProblemNotEnoughCandidates())
+  await updateCouncilStage(store, stage, event.blockNumber, ElectionProblem.NOT_ENOUGH_CANDIDATES)
 }
 
 /*
@@ -360,21 +356,11 @@ export async function council_VotingPeriodStarted({ event, store }: EventContext
   The event is emitted when a member announces candidacy to the council.
 */
 export async function council_NewCandidate({ event, store }: EventContext & StoreContext): Promise<void> {
-  // common event processing
+  // common event processing - init
 
   const [memberId, stakingAccount, rewardAccount, balance] = new Council.NewCandidateEvent(event).params
   const member = await getMembership(store, memberId.toString())
 
-  const newCandidateEvent = new NewCandidateEvent({
-    ...genericEventFields(event),
-    member,
-    stakingAccount: stakingAccount.toString(),
-    rewardAccount: rewardAccount.toString(),
-    balance,
-  })
-
-  await store.save<NewCandidateEvent>(newCandidateEvent)
-
   // specific event processing
 
   // increase candidate count in stage update record
@@ -408,24 +394,29 @@ export async function council_NewCandidate({ event, store }: EventContext & Stor
     noteMetadata,
   })
   await store.save<Candidate>(candidate)
+
+  // common event processing - save
+
+  const newCandidateEvent = new NewCandidateEvent({
+    ...genericEventFields(event),
+    candidate,
+    stakingAccount: stakingAccount.toString(),
+    rewardAccount: rewardAccount.toString(),
+    balance,
+  })
+
+  await store.save<NewCandidateEvent>(newCandidateEvent)
 }
 
 /*
   The event is emitted when the new council is elected. Sufficient members were elected and there is no other problem.
 */
 export async function council_NewCouncilElected({ event, store }: EventContext & StoreContext): Promise<void> {
-  // common event processing
+  // common event processing - init
 
   const [memberIds] = new Council.NewCouncilElectedEvent(event).params
   const members = await store.getMany(Membership, { where: { id: memberIds.map((item) => item.toString()) } })
 
-  const newCouncilElectedEvent = new NewCouncilElectedEvent({
-    ...genericEventFields(event),
-    electedMembers: members,
-  })
-
-  await store.save<NewCouncilElectedEvent>(newCouncilElectedEvent)
-
   // specific event processing
 
   // mark old council as resinged
@@ -463,6 +454,15 @@ export async function council_NewCouncilElected({ event, store }: EventContext &
 
   // end the last election round and start new one
   await startNextElectionRound(store, electedCouncil, electionRound)
+
+  // common event processing - save
+
+  const newCouncilElectedEvent = new NewCouncilElectedEvent({
+    ...genericEventFields(event),
+    electedCouncil,
+  })
+
+  await store.save<NewCouncilElectedEvent>(newCouncilElectedEvent)
 }
 
 /*
@@ -495,10 +495,11 @@ export async function council_CandidacyStakeRelease({ event, store }: EventConte
 
   const [memberId] = new Council.CandidacyStakeReleaseEvent(event).params
   const member = await getMembership(store, memberId.toString())
+  const candidate = await getCandidate(store, memberId.toString()) // get last member's candidacy record
 
   const candidacyStakeReleaseEvent = new CandidacyStakeReleaseEvent({
     ...genericEventFields(event),
-    member,
+    candidate,
   })
 
   await store.save<CandidacyStakeReleaseEvent>(candidacyStakeReleaseEvent)
@@ -506,7 +507,6 @@ export async function council_CandidacyStakeRelease({ event, store }: EventConte
   // specific event processing
 
   // update candidate info about stake lock
-  const candidate = await getCandidate(store, memberId.toString()) // get last member's candidacy record
   candidate.stakeLocked = false
   await store.save<Candidate>(candidate)
 }
@@ -552,10 +552,15 @@ export async function council_CandidacyNoteSet({ event, store }: EventContext &
   // unpack note's metadata and save it to db
   const metadata = deserializeMetadata(CouncilCandidacyNoteMetadata, note)
   const noteMetadata = candidate.noteMetadata
-  noteMetadata.header = metadata?.header || undefined
+  // `XXX || (null as any)` construct clears metadata if requested (see https://github.com/Joystream/hydra/issues/435)
+  noteMetadata.header = isSet(metadata?.header) ? metadata?.header || (null as any) : metadata?.header
   noteMetadata.bulletPoints = metadata?.bulletPoints || []
-  noteMetadata.bannerImageUri = metadata?.bannerImageUri || undefined
-  noteMetadata.description = metadata?.description || undefined
+  noteMetadata.bannerImageUri = isSet(metadata?.bannerImageUri)
+    ? metadata?.bannerImageUri || (null as any)
+    : metadata?.bannerImageUri
+  noteMetadata.description = isSet(metadata?.description)
+    ? metadata?.description || (null as any)
+    : metadata?.description
   await store.save<CandidacyNoteMetadata>(noteMetadata)
 
   const candidacyNoteSetEvent = new CandidacyNoteSetEvent({
@@ -781,7 +786,7 @@ export async function referendum_ReferendumFinished({ event, store }: EventConte
       (item, index) =>
         new ReferendumStageRevealingOptionResult({
           votePower: item.vote_power,
-          option: members[index],
+          option: members.find((tmpMember) => tmpMember.id.toString() == optionResultsRaw[index].option_id.toString()),
         })
     ),
   })
@@ -795,27 +800,17 @@ export async function referendum_ReferendumFinished({ event, store }: EventConte
   The event is emitted when a vote is casted in the council election.
 */
 export async function referendum_VoteCast({ event, store }: EventContext & StoreContext): Promise<void> {
-  // common event processing
+  // common event processing - init
 
   const [account, hash, stake] = new Referendum.VoteCastEvent(event).params
   const votePower = calculateVotePower(account.toString(), stake)
-  const hashString = bytesToString(hash)
-
-  const voteCastEvent = new VoteCastEvent({
-    ...genericEventFields(event),
-    account: account.toString(),
-    hash: hashString,
-    votePower,
-  })
-
-  await store.save<VoteCastEvent>(voteCastEvent)
 
   // specific event processing
 
   const electionRound = await getCurrentElectionRound(store)
 
   const castVote = new CastVote({
-    commitment: hashString,
+    commitment: hash.toString(),
     electionRound,
     stake,
     stakeLocked: true,
@@ -823,26 +818,26 @@ export async function referendum_VoteCast({ event, store }: EventContext & Store
     votePower: votePower,
   })
   await store.save<CastVote>(castVote)
+
+  // common event processing - save
+
+  const voteCastEvent = new VoteCastEvent({
+    ...genericEventFields(event),
+    castVote,
+  })
+
+  await store.save<VoteCastEvent>(voteCastEvent)
 }
 
 /*
   The event is emitted when a previously casted vote is revealed.
 */
 export async function referendum_VoteRevealed({ event, store }: EventContext & StoreContext): Promise<void> {
-  // common event processing
+  // common event processing - init
 
   const [account, memberId, salt] = new Referendum.VoteRevealedEvent(event).params
   const member = await getMembership(store, memberId.toString())
 
-  const voteRevealedEvent = new VoteRevealedEvent({
-    ...genericEventFields(event),
-    account: account.toString(),
-    member: member,
-    salt: bytesToString(salt),
-  })
-
-  await store.save<VoteRevealedEvent>(voteRevealedEvent)
-
   // specific event processing
 
   // read vote info
@@ -856,6 +851,15 @@ export async function referendum_VoteRevealed({ event, store }: EventContext & S
   const candidate = await getCandidate(store, memberId.toString(), electionRound)
   candidate.votePower = candidate.votePower.add(castVote.votePower)
   await store.save<Candidate>(candidate)
+
+  // common event processing - save
+
+  const voteRevealedEvent = new VoteRevealedEvent({
+    ...genericEventFields(event),
+    castVote,
+  })
+
+  await store.save<VoteRevealedEvent>(voteRevealedEvent)
 }
 
 /*

+ 0 - 1
query-node/mappings/membership.ts

@@ -109,7 +109,6 @@ async function createNewMemberFromParams(
     councilMembers: [],
     referendumStageRevealingOptionResults: [],
     votesRecieved: [],
-    electedCouncilEvents: [],
   })
 
   await store.save<MemberMetadata>(member.metadata)

+ 12 - 16
query-node/schemas/council.graphql

@@ -41,22 +41,11 @@ type CouncilStageIdle @variant {
 
 union CouncilStage = CouncilStageAnnouncing | CouncilStageElection | CouncilStageIdle | VariantNone
 
-type ElectionProblemNotEnoughCandidates @variant {
-  # no properties
-
-  # TODO: remove me - variant needs to have at least 1 property now
-  dummy: Int
+enum ElectionProblem {
+  NOT_ENOUGH_CANDIDATES
+  NEW_COUNCIL_NOT_ELECTED
 }
 
-type ElectionProblemNewCouncilNotElected @variant {
-  # no properties
-
-  # TODO: remove me - variant needs to have at least 1 property now
-  dummy: Int
-}
-
-union ElectionProblem = ElectionProblemNotEnoughCandidates | ElectionProblemNewCouncilNotElected | VariantNone
-
 type Candidate @entity {
   "Account used for staking currency needed for the candidacy."
   stakingAccountId: String!
@@ -179,11 +168,16 @@ type ReferendumStageRevealingOptionResult @entity {
   referendumFinishedEvent: ReferendumFinishedEvent!
 }
 
+# This section is not useful before referencing variant is solved.
+# See commented reference in ElectionRound, for example.
+# Uncomment after solving the issue or delete if it can't be solved or is not needed
+# in the future.
+#
 # TODO: this maybe needs to be @entity - so it's saved in db
-union ReferendumStage = ReferendumStageInactive | ReferendumStageVoting | ReferendumStageRevealing | VariantNone
+#union ReferendumStage = ReferendumStageInactive | ReferendumStageVoting | ReferendumStageRevealing | VariantNone
 
 type CastVote @entity {
-  "Hashed vote that was casted before being revealed."
+  "Hashed vote that was casted before being revealed. Hex format."
   commitment: String!
 
   "Election round."
@@ -258,6 +252,8 @@ type ElectionRound @entity {
   candidates: [Candidate!]! @derivedFrom(field: "electionRound")
 }
 
+# Not yet sure if this will be needed by apps using query node.
+#
 #type Budget @entity {
 #  "Block number at which the next rewards will be paid."
 #  nextRewardPaymentsAt: BigInt!

+ 10 - 22
query-node/schemas/councilEvents.graphql

@@ -86,8 +86,8 @@ type NewCandidateEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "Candidate's membership."
-  member: Membership!
+  "Related candidate."
+  candidate: Candidate!
 
   "Candidate's account used to stake currency."
   stakingAccount: String!
@@ -119,8 +119,8 @@ type NewCouncilElectedEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "Candidates' memberships."
-  electedMembers: [Membership!]
+  "Newly elected council."
+  electedCouncil: ElectedCouncil!
 }
 
 type NewCouncilNotElectedEvent implements Event @entity {
@@ -164,8 +164,8 @@ type CandidacyStakeReleaseEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "Candidate's membership."
-  member: Membership!
+  "Related candidate."
+  candidate: Candidate!
 }
 
 type CandidacyWithdrawEvent implements Event @entity {
@@ -513,14 +513,8 @@ type VoteCastEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "Account that cast the vote."
-  account: String!
-
-  "Hash of sealed vote."
-  hash: String!
-
-  "Vote power decided by amount staked."
-  votePower: BigInt!
+  "Vote cast."
+  castVote: CastVote!
 }
 
 type VoteRevealedEvent implements Event @entity {
@@ -543,14 +537,8 @@ type VoteRevealedEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "Account that cast a vote."
-  account: String!
-
-  "Membership of user that cast the vote."
-  member: Membership!
-
-  "Salt that has been used for the vote's hash creation."
-  salt: String!
+  "Vote cast."
+  castVote: CastVote!
 }
 
 type StakeReleasedEvent implements Event @entity {

+ 0 - 3
query-node/schemas/membership.graphql

@@ -97,9 +97,6 @@ type Membership @entity {
 
   "Votes recieved in referendums by this member."
   votesRecieved: [CastVote!] @derivedFrom(field: "voteFor")
-
-  "Events announcing council being elected."
-  electedCouncilEvents: [NewCouncilElectedEvent!] @derivedFrom(field: "electedMembers")
 }
 
 type MembershipSystemSnapshot @entity {