Browse Source

Refactor mappings

Theophile Sandoz 3 years ago
parent
commit
1a975e9ad3
1 changed files with 84 additions and 74 deletions
  1. 84 74
      query-node/mappings/src/bounty.ts

+ 84 - 74
query-node/mappings/src/bounty.ts

@@ -1,4 +1,4 @@
-import { DatabaseManager, EventContext, StoreContext } from '@joystream/hydra-common'
+import { DatabaseManager, EventContext, StoreContext, SubstrateEvent } from '@joystream/hydra-common'
 import { BountyMetadata } from '@joystream/metadata-protobuf'
 import { AssuranceContractType, BountyActor, BountyId, EntryId, FundingType } from '@joystream/types/augment'
 import {
@@ -65,6 +65,40 @@ async function getEntry(store: DatabaseManager, entryId: EntryId): Promise<Bount
   return entry
 }
 
+interface BountyEvent {
+  ctx: SubstrateEvent
+  params: [BountyId, ...any]
+}
+async function updateBounty(store: DatabaseManager, event: BountyEvent, changes: (bounty: Bounty) => Partial<Bounty>) {
+  const [bountyId] = event.params
+  const bounty = await getBounty(store, bountyId)
+  bounty.updatedAt = new Date(event.ctx.blockTimestamp)
+  Object.assign(bounty, changes(bounty))
+
+  await store.save<BountyEntry>(bounty)
+
+  return bounty
+}
+
+interface EntryEvent {
+  ctx: SubstrateEvent
+  params: [any, EntryId, ...any]
+}
+async function updateEntry(
+  store: DatabaseManager,
+  event: EntryEvent,
+  changes: (bounty: BountyEntry) => Partial<BountyEntry>
+) {
+  const [, entryId] = event.params
+  const entry = await getEntry(store, entryId)
+  entry.updatedAt = new Date(event.ctx.blockTimestamp)
+  Object.assign(entry, changes(entry))
+
+  await store.save<BountyEntry>(entry)
+
+  return entry
+}
+
 function bountyActorToMembership(actor: BountyActor): Membership | undefined {
   if (actor.isMember) {
     return new Membership({ id: String(actor.asMember) })
@@ -159,6 +193,7 @@ export async function bounty_BountyCreated({ event, store }: EventContext & Stor
 
   const metadata = deserializeMetadata(BountyMetadata, metadataBytes)
 
+  // Create the bounty
   const bounty = new Bounty({
     id: String(bountyId),
     createdAt: eventTime,
@@ -179,11 +214,11 @@ export async function bounty_BountyCreated({ event, store }: EventContext & Stor
     totalFunding: bountyParams.cherry,
     discussionThread: asForumThread(metadata?.discussionThread ?? undefined),
   })
-
   await store.save<Bounty>(bounty)
 
   bountyScheduleFundingEnd(store, bounty)
 
+  // Record the event
   const createdInEvent = new BountyCreatedEvent({ ...genericEventFields(event), bounty })
   await store.save<BountyCreatedEvent>(createdInEvent)
 
@@ -218,7 +253,7 @@ export async function bounty_BountyCreated({ event, store }: EventContext & Stor
   }
 }
 
-// Store bounty canceled events
+// Store bounties canceled events
 export async function bounty_BountyCanceled({ event, store }: EventContext & StoreContext): Promise<void> {
   const bountyCanceledEvent = new BountyEvents.BountyCanceledEvent(event)
   const [bountyId] = bountyCanceledEvent.params
@@ -229,7 +264,7 @@ export async function bounty_BountyCanceled({ event, store }: EventContext & Sto
   await store.save<BountyCanceledEvent>(canceledEvent)
 }
 
-// Store bounty vetoed events
+// Store bounties vetoed events
 export async function bounty_BountyVetoed({ event, store }: EventContext & StoreContext): Promise<void> {
   const bountyVetoedEvent = new BountyEvents.BountyVetoedEvent(event)
   const [bountyId] = bountyVetoedEvent.params
@@ -239,19 +274,18 @@ export async function bounty_BountyVetoed({ event, store }: EventContext & Store
   await store.save<BountyVetoedEvent>(vetoedEvent)
 }
 
-// Store new contributions and their BountyFunded events
+// Store new contributions and add their amount to their bounty totalFunding
 export async function bounty_BountyFunded({ event, store }: EventContext & StoreContext): Promise<void> {
   const bountyFundedEvent = new BountyEvents.BountyFundedEvent(event)
-  const [bountyId, contributorActor, amount] = bountyFundedEvent.params
+  const [, contributorActor, amount] = bountyFundedEvent.params
   const eventTime = new Date(event.blockTimestamp)
 
-  const bounty = await getBounty(store, bountyId)
-
-  bounty.updatedAt = eventTime
-  bounty.totalFunding = bounty.totalFunding.add(amount)
-
-  await store.save<Bounty>(bounty)
+  // Update the bounty totalFunding
+  const bounty = await updateBounty(store, bountyFundedEvent, (bounty) => ({
+    totalFunding: bounty.totalFunding.add(amount),
+  }))
 
+  // Create the contribution
   const contribution = new BountyContribution({
     createdAt: eventTime,
     updatedAt: eventTime,
@@ -259,168 +293,144 @@ export async function bounty_BountyFunded({ event, store }: EventContext & Store
     contributor: bountyActorToMembership(contributorActor),
     amount,
   })
-
   await store.save<BountyContribution>(contribution)
 
+  // Record the event
   const fundedEvent = new BountyFundedEvent({ ...genericEventFields(event), contribution })
-
   await store.save<BountyFundedEvent>(fundedEvent)
 }
 
-// Store BountyMaxFundingReached event and update the bounty stage
+// Start bounties working stage
 export async function bounty_BountyMaxFundingReached({ event, store }: EventContext & StoreContext): Promise<void> {
   const maxFundingReachedEvent = new BountyEvents.BountyMaxFundingReachedEvent(event)
   const [bountyId] = maxFundingReachedEvent.params
 
+  // Update the bounty stage
+  const bounty = await getBounty(store, bountyId)
+  await endFundingPeriod(store, bounty)
+
   // Record the event
-  const bounty = new Bounty({ id: String(bountyId) })
   const maxFundingReachedInEvent = new BountyMaxFundingReachedEvent({ ...genericEventFields(event), bounty })
-
   await store.save<BountyMaxFundingReachedEvent>(maxFundingReachedInEvent)
-
-  // Update the bounty stage
-  endFundingPeriod(store, bounty)
 }
 
+// Store BountyFundingWithdrawal events (also update the contribution deleteAt time)
 export async function bounty_BountyFundingWithdrawal({ event, store }: EventContext & StoreContext): Promise<void> {
   const fundingWithdrawalEvent = new BountyEvents.BountyFundingWithdrawalEvent(event)
   const [bountyId, contributorActor] = fundingWithdrawalEvent.params
   const eventTime = new Date(event.blockTimestamp)
 
+  // Update the contribution
   const contributor = bountyActorToMembership(contributorActor)
   const contribution = await getContribution(store, bountyId, contributor?.id)
+  contribution.updatedAt = eventTime
+  contribution.deletedAt = eventTime
+  await store.save<BountyContribution>(contribution)
 
   // Update the bounty totalFunding
-  const bounty = await getBounty(store, bountyId)
-  bounty.updatedAt = eventTime
-  bounty.totalFunding = bounty.totalFunding.sub(contribution.amount)
-
-  await store.save<Bounty>(bounty)
+  await updateBounty(store, fundingWithdrawalEvent, (bounty) => ({
+    totalFunding: bounty.totalFunding.sub(contribution.amount),
+  }))
 
   // Record the event
   const withdrawnInEvent = new BountyFundingWithdrawalEvent({ ...genericEventFields(event), contribution })
-
   await store.save<BountyFundingWithdrawalEvent>(withdrawnInEvent)
 }
 
+// Remove the cherries amount from their bounty totalFunding
 export async function bounty_BountyCreatorCherryWithdrawal({
   event,
   store,
 }: EventContext & StoreContext): Promise<void> {
   const cherryWithdrawalEvent = new BountyEvents.BountyCreatorCherryWithdrawalEvent(event)
-  const [bountyId] = cherryWithdrawalEvent.params
-  const eventTime = new Date(event.blockTimestamp)
 
   // Update the bounty totalFunding
-  const bounty = await getBounty(store, bountyId)
-  bounty.updatedAt = eventTime
-  bounty.totalFunding = bounty.totalFunding.sub(bounty.cherry)
-
-  await store.save<Bounty>(bounty)
+  const bounty = await updateBounty(store, cherryWithdrawalEvent, (bounty) => ({
+    totalFunding: bounty.totalFunding.sub(bounty.cherry),
+  }))
 
   // Record the event
   const withdrawnInEvent = new BountyCreatorCherryWithdrawalEvent({ ...genericEventFields(event), bounty })
-
   await store.save<BountyCreatorCherryWithdrawalEvent>(withdrawnInEvent)
 }
 
+// Terminate removed bounties
 export async function bounty_BountyRemoved({ event, store }: EventContext & StoreContext): Promise<void> {
   const bountyRemovedEvent = new BountyEvents.BountyRemovedEvent(event)
-  const [bountyId] = bountyRemovedEvent.params
-  const eventTime = new Date(event.blockTimestamp)
-
-  const bounty = await getBounty(store, bountyId)
 
   // Terminate the bounty
-  bounty.updatedAt = eventTime
-  bounty.deletedAt = eventTime
-  bounty.stage = BountyStage.Terminated
-
-  await store.save<Bounty>(bounty)
+  const bounty = await updateBounty(store, bountyRemovedEvent, (bounty) => ({
+    deletedAt: bounty.updatedAt,
+    stage: BountyStage.Terminated,
+  }))
 
   // Record the event
   const removedInEvent = new BountyRemovedEvent({ ...genericEventFields(event), bounty })
-
   await store.save<BountyRemovedEvent>(removedInEvent)
 }
 
+// Store new entries
 export async function bounty_WorkEntryAnnounced({ event, store }: EventContext & StoreContext): Promise<void> {
   const entryAnnouncedEvent = new BountyEvents.WorkEntryAnnouncedEvent(event)
   const [bountyId, entryId, memberId, accountId] = entryAnnouncedEvent.params
   const eventTime = new Date(event.blockTimestamp)
 
-  const bounty = new Bounty({ id: String(bountyId) })
-
   // Create the entry
   const entry = new BountyEntry({
     id: String(entryId),
     createdAt: eventTime,
     updatedAt: eventTime,
-    bounty,
+    bounty: new Bounty({ id: String(bountyId) }),
     worker: new Membership({ id: String(memberId) }),
     stakingAccount: String(accountId),
     workSubmitted: false,
     status: new BountyEntryStatusWorking(),
   })
-
   await store.save<BountyEntry>(entry)
 
   // Record the event
   const announcedEvent = new WorkEntryAnnouncedEvent({ ...genericEventFields(event), entry })
-
   await store.save<WorkEntryAnnouncedEvent>(announcedEvent)
 }
 
+// Change withdrawn entries status to withdrawn
 export async function bounty_WorkEntryWithdrawn({ event, store }: EventContext & StoreContext): Promise<void> {
   const entryWithdrawnEvent = new BountyEvents.WorkEntryWithdrawnEvent(event)
-  const [, entryId] = entryWithdrawnEvent.params
-  const eventTime = new Date(event.blockTimestamp)
 
   // Update the entry status
-  const entry = await getEntry(store, entryId)
-  entry.updatedAt = eventTime
-  entry.status = new BountyEntryStatusWithdrawn()
-
-  await store.save<BountyEntry>(entry)
+  const entry = await updateEntry(store, entryWithdrawnEvent, () => ({
+    status: new BountyEntryStatusWithdrawn(),
+  }))
 
   // Record the event
   const withdrawnInEvent = new WorkEntryWithdrawnEvent({ ...genericEventFields(event), entry })
-
   await store.save<WorkEntryWithdrawnEvent>(withdrawnInEvent)
 }
 
+// Store WorkEntrySlashed events
 export async function bounty_WorkEntrySlashed({ event, store }: EventContext & StoreContext): Promise<void> {
   const entrySlashedEvent = new BountyEvents.WorkEntrySlashedEvent(event)
-  const [, entryId] = entrySlashedEvent.params
-  const eventTime = new Date(event.blockTimestamp)
 
   // Update the entry status
-  const entry = await getEntry(store, entryId)
-  entry.updatedAt = eventTime
-  entry.status = new BountyEntryStatusRejected()
-
-  await store.save<BountyEntry>(entry)
+  const entry = await updateEntry(store, entrySlashedEvent, () => ({
+    status: new BountyEntryStatusRejected(),
+  }))
 
   // Record the event
   const slashedInEvent = new WorkEntrySlashedEvent({ ...genericEventFields(event), entry })
-
   await store.save<WorkEntrySlashedEvent>(slashedInEvent)
 }
 
+// Store WorkSubmitted events
 export async function bounty_WorkSubmitted({ event, store }: EventContext & StoreContext): Promise<void> {
   const entrySlashedEvent = new BountyEvents.WorkEntrySlashedEvent(event)
-  const [, entryId] = entrySlashedEvent.params
-  const eventTime = new Date(event.blockTimestamp)
-
-  // Update the entry
-  const entry = await getEntry(store, entryId)
-  entry.updatedAt = eventTime
-  entry.workSubmitted = true
 
-  await store.save<BountyEntry>(entry)
+  // Update the entry status
+  const entry = await updateEntry(store, entrySlashedEvent, () => ({
+    workSubmitted: true,
+  }))
 
   // Record the event
   const submittedInEvent = new WorkSubmittedEvent({ ...genericEventFields(event), entry })
-
   await store.save<WorkEntrySlashedEvent>(submittedInEvent)
 }