Browse Source

Map newly created bounties

Theophile Sandoz 3 years ago
parent
commit
8a657ac936
3 changed files with 113 additions and 0 deletions
  1. 18 0
      query-node/manifest.yml
  2. 94 0
      query-node/mappings/src/bounty.ts
  3. 1 0
      query-node/mappings/src/index.ts

+ 18 - 0
query-node/manifest.yml

@@ -165,6 +165,21 @@ typegen:
     - referendum.VoteCast
     - referendum.VoteRevealed
     - referendum.StakeReleased
+    # Bounty
+    - bounty.BountyCreated
+    - bounty.BountyCanceled
+    - bounty.BountyVetoed
+    - bounty.BountyFunded
+    - bounty.BountyMaxFundingReached
+    - bounty.BountyFundingWithdrawal
+    - bounty.BountyCreatorCherryWithdrawal
+    - bounty.BountyRemoved
+    - bounty.WorkEntryAnnounced
+    - bounty.WorkEntryWithdrawn
+    - bounty.WorkEntrySlashed
+    - bounty.WorkSubmitted
+    - bounty.OracleJudgmentSubmitted
+    - bounty.WorkEntrantFundsWithdrawn
   calls:
     # Proposals discussion
     - proposalsDiscussion.addPost
@@ -841,6 +856,9 @@ mappings:
       handler: referendum_VoteRevealed
     - event: referendum.StakeReleased
       handler: referendum_StakeReleased
+    # Bounty
+    - event: bounty.BountyCreated
+      handler: bounty_BountyCreated
   extrinsicHandlers:
     # infer defaults here
     #- extrinsic: Balances.Transfer

+ 94 - 0
query-node/mappings/src/bounty.ts

@@ -0,0 +1,94 @@
+import { EventContext, StoreContext } from '@joystream/hydra-common'
+import { BountyMetadata } from '@joystream/metadata-protobuf'
+import { AssuranceContractType, BountyActor, BountyId, FundingType } from '@joystream/types/augment'
+import {
+  Bounty,
+  BountyContractClosed,
+  BountyContractOpen,
+  BountyCreatedEvent,
+  BountyFundingLimited,
+  BountyFundingPerpetual,
+  BountyStage,
+  ForumThread,
+  Membership,
+} from 'query-node/dist/model'
+import { Bounty as BountyEvents } from '../generated/types'
+import { deserializeMetadata, genericEventFields } from './common'
+
+/**
+ * Commons helpers
+ */
+
+function bountyActorToMembership(actor: BountyActor): Membership | undefined {
+  if (actor.isMember) {
+    return new Membership({ id: String(actor.asMember) })
+  }
+}
+
+/**
+ * Event handlers
+ */
+
+export async function bounty_BountyCreated({ event, store }: EventContext & StoreContext): Promise<void> {
+  const createdEvent = new BountyEvents.BountyCreatedEvent(event)
+  const [bountyId, bountyParams, metadataBytes] = createdEvent.params
+  const eventTime = new Date(event.blockTimestamp)
+
+  const metadata = deserializeMetadata(BountyMetadata, metadataBytes)
+
+  const bounty = new Bounty({
+    id: String(bountyId),
+    createdAt: eventTime,
+    updatedAt: eventTime,
+    title: metadata?.title ?? undefined,
+    description: metadata?.description ?? undefined,
+    bannerImageUri: metadata?.bannerImageUri ?? undefined,
+    cherry: bountyParams.cherry,
+    entrantStake: bountyParams.entrant_stake,
+    creator: bountyActorToMembership(bountyParams.creator),
+    oracle: bountyActorToMembership(bountyParams.oracle),
+    fundingType: asFundingType(bountyParams.funding_type),
+    contractType: asContractType(bountyParams.contract_type),
+    workPeriod: bountyParams.work_period.toNumber(),
+    judgingPeriod: bountyParams.judging_period.toNumber(),
+
+    stage: BountyStage.Funding,
+    totalFunding: bountyParams.cherry,
+    discussionThread: asForumThread(metadata?.discussionThread ?? undefined),
+  })
+
+  await store.save<Bounty>(bounty)
+
+  const createdInEvent = new BountyCreatedEvent({ ...genericEventFields(event), bounty })
+  await store.save<BountyCreatedEvent>(createdInEvent)
+
+  function asFundingType(funding: FundingType) {
+    if (funding.isPerpetual) {
+      const perpetualFunding = new BountyFundingPerpetual()
+      perpetualFunding.target = funding.asPerpetual.target
+      return perpetualFunding
+    } else {
+      const limitedFunding = new BountyFundingLimited()
+      limitedFunding.maxFundingAmount = funding.asLimited.max_funding_amount
+      limitedFunding.minFundingAmount = funding.asLimited.min_funding_amount
+      limitedFunding.fundingPeriod = funding.asLimited.funding_period.toNumber()
+      return limitedFunding
+    }
+  }
+
+  function asContractType(assuranceContract: AssuranceContractType) {
+    if (assuranceContract.isOpen) {
+      return new BountyContractOpen()
+    } else {
+      const closedContract = new BountyContractClosed()
+      closedContract.whitelist = assuranceContract.asClosed.map((id) => new Membership({ id: String(id) }))
+      return closedContract
+    }
+  }
+
+  function asForumThread(threadId: number | undefined) {
+    if (typeof threadId === 'number') {
+      return new ForumThread({ id: String(threadId) })
+    }
+  }
+}

+ 1 - 0
query-node/mappings/src/index.ts

@@ -9,6 +9,7 @@ export * from './content'
 export * from './membership'
 export * from './storage'
 export * from './council'
+export * from './bounty'
 export * from './workingGroups'
 export * from './proposals'
 export * from './proposalsDiscussion'