Browse Source

query node - content nft mappings II

ondratra 3 years ago
parent
commit
fcf5e85ab8

+ 387 - 69
query-node/mappings/content/nft.ts

@@ -1,9 +1,7 @@
 // TODO: solve events' relations to videos and other entites that can be changed or deleted
-// TODO: solve transactionalStatus for OwnedNFT + how to set it up for first time auctioned NFT?
-// TODO: walkthrough bidding events once again and ensure all data are saved properly
 
 import { EventContext, StoreContext, DatabaseManager } from '@joystream/hydra-common'
-import { genericEventFields, inconsistentState } from '../common'
+import { genericEventFields, inconsistentState, unexpectedData, logger } from '../common'
 import {
   // entities
   Auction,
@@ -14,6 +12,14 @@ import {
   Membership,
   OwnedNft,
   Video,
+  TransactionalStatusInitiatedOfferToMember,
+  TransactionalStatusIdle,
+  TransactionalStatusBuyNow,
+  TransactionalStatusAuction,
+  ContentActor,
+  ContentActorMember,
+  ContentActorCurator,
+  Curator,
 
   // events
   AuctionStartedEvent,
@@ -33,6 +39,7 @@ import {
 } from 'query-node/dist/model'
 import * as joystreamTypes from '@joystream/types/augment/all/types'
 import { Content } from '../generated/types'
+import { FindConditions } from 'typeorm'
 import BN from 'bn.js'
 
 // definition of generic type for Hydra DatabaseManager's methods
@@ -92,6 +99,45 @@ async function getAuctionFromVideo(
   }
 }
 
+async function getNftFromVideo(
+  store: DatabaseManager,
+  videoId: string,
+  errorMessageForVideo: string,
+  errorMessageForNft: string
+): Promise<{ video: Video; nft: OwnedNft }> {
+  // load video
+  const video = await getRequiredExistingEntity(store, Video, videoId.toString(), errorMessageForVideo, ['nft'])
+
+  // get auction
+  const nft = video.nft
+
+  // ensure auction exists
+  if (!nft) {
+    return inconsistentState(errorMessageForNft, videoId)
+  }
+
+  return {
+    video,
+    nft,
+  }
+}
+
+async function resetNftTransactionalStatusFromVideo(store: DatabaseManager, videoId: string, errorMessage: string) {
+  // load NFT
+  const nft = await store.get(OwnedNft, { where: { video: { id: videoId.toString() } } as FindConditions<OwnedNft> })
+
+  // ensure NFT
+  if (!nft) {
+    return inconsistentState(errorMessage, videoId.toString())
+  }
+
+  // reset transactional status
+  nft.transactionalStatus = new TransactionalStatusIdle()
+
+  // save NFT
+  await store.save<OwnedNft>(nft)
+}
+
 async function getRequiredExistingEntites<Type extends Video | Membership>(
   store: DatabaseManager,
   entityType: EntityType<Type>,
@@ -117,17 +163,53 @@ async function getRequiredExistingEntites<Type extends Video | Membership>(
   return entities
 }
 
+async function convertContentActor(
+  store: DatabaseManager,
+  contentActor: joystreamTypes.ContentActor
+): Promise<typeof ContentActor> {
+  if (contentActor.isMember) {
+    const memberId = contentActor.asMember.toNumber()
+    const member = await store.get(Membership, { where: { id: memberId.toString() } as FindConditions<Membership> })
+
+    // ensure member exists
+    if (!member) {
+      return inconsistentState(`Actor is non-existing member`, memberId)
+    }
+
+    const result = new ContentActorMember()
+    result.member = member
+
+    return result
+  }
+
+  if (contentActor.isCurator) {
+    const curatorId = contentActor.asCurator[1].toNumber()
+    const curator = await store.get(Curator, {
+      where: { id: curatorId.toString() } as FindConditions<Curator>,
+    })
+
+    // ensure curator group exists
+    if (!curator) {
+      return inconsistentState('Actor is non-existing curator group', curatorId)
+    }
+
+    const result = new ContentActorCurator()
+    result.curator = curator
+
+    return result
+  }
+
+  // contentActor.isLead not supported (not needed) now
+
+  logger.error('Not implemented ContentActor type', { contentActor: contentActor.toString() })
+  throw new Error('Not-implemented ContentActor type used')
+}
+
 export async function contentNft_AuctionStarted({ event, store }: EventContext & StoreContext): Promise<void> {
   // common event processing
 
   const [ownerId, videoId, auctionParams] = new Content.AuctionStartedEvent(event).params
 
-  const announcingPeriodStartedEvent = new AuctionStartedEvent({
-    ...genericEventFields(event),
-  })
-
-  await store.save<AuctionStartedEvent>(announcingPeriodStartedEvent)
-
   // specific event processing
 
   // load video
@@ -135,9 +217,15 @@ export async function contentNft_AuctionStarted({ event, store }: EventContext &
     store,
     Video,
     videoId.toString(),
-    `Non-existing video's auction started`
+    `Non-existing video's auction started`,
+    ['nft']
   )
 
+  // ensure NFT has been issued
+  if (!video.nft) {
+    return inconsistentState('Non-existing NFT auctioned', video.id.toString())
+  }
+
   // load member
   const member = await getRequiredExistingEntity(
     store,
@@ -169,6 +257,29 @@ export async function contentNft_AuctionStarted({ event, store }: EventContext &
 
   // save auction
   await store.save<Auction>(auction)
+
+  const transactionalStatus = new TransactionalStatusAuction()
+  transactionalStatus.auction = auction
+
+  video.nft.transactionalStatus = transactionalStatus
+
+  // save NFT
+  await store.save<OwnedNft>(video.nft)
+
+  // common event processing - second
+
+  const actor = new ContentActorMember()
+  actor.member = new Membership({ id: ownerId.toString() })
+
+  const announcingPeriodStartedEvent = new AuctionStartedEvent({
+    ...genericEventFields(event),
+
+    actor,
+    video,
+    auction,
+  })
+
+  await store.save<AuctionStartedEvent>(announcingPeriodStartedEvent)
 }
 
 // create auction type variant from raw runtime auction type
@@ -198,12 +309,6 @@ export async function contentNft_NftIssued({ event, store }: EventContext & Stor
 
   const [actor, videoId, royalty, metadata, mbNewOwnerId] = new Content.NftIssuedEvent(event).params
 
-  const announcingPeriodStartedEvent = new NftIssuedEvent({
-    ...genericEventFields(event),
-  })
-
-  await store.save<NftIssuedEvent>(announcingPeriodStartedEvent)
-
   // specific event processing
 
   // load video
@@ -220,10 +325,25 @@ export async function contentNft_NftIssued({ event, store }: EventContext & Stor
     ownerMember: newOwner,
     creatorRoyalty,
     metadata: metadata.toString(),
+    transactionalStatus: new TransactionalStatusIdle(),
   })
 
   // save nft
   await store.save<OwnedNft>(ownedNft)
+
+  // common event processing - second
+
+  const announcingPeriodStartedEvent = new NftIssuedEvent({
+    ...genericEventFields(event),
+
+    contentActor: await convertContentActor(store, actor),
+    video,
+    royalty: creatorRoyalty,
+    metadata: metadata.toString(),
+    newOwner,
+  })
+
+  await store.save<NftIssuedEvent>(announcingPeriodStartedEvent)
 }
 
 export async function contentNft_AuctionBidMade({ event, store }: EventContext & StoreContext): Promise<void> {
@@ -231,12 +351,6 @@ export async function contentNft_AuctionBidMade({ event, store }: EventContext &
 
   const [memberId, videoId, bidAmount, extendsAuction] = new Content.AuctionBidMadeEvent(event).params
 
-  const announcingPeriodStartedEvent = new AuctionBidMadeEvent({
-    ...genericEventFields(event),
-  })
-
-  await store.save<AuctionBidMadeEvent>(announcingPeriodStartedEvent)
-
   // specific event processing
 
   // load member
@@ -272,6 +386,19 @@ export async function contentNft_AuctionBidMade({ event, store }: EventContext &
   auction.lastBid = bid
 
   await store.save<Auction>(auction)
+
+  // common event processing - second
+
+  const announcingPeriodStartedEvent = new AuctionBidMadeEvent({
+    ...genericEventFields(event),
+
+    member,
+    video,
+    bidAmount,
+    extendsAuction: extendsAuction.isTrue,
+  })
+
+  await store.save<AuctionBidMadeEvent>(announcingPeriodStartedEvent)
 }
 
 export async function contentNft_AuctionBidCanceled({ event, store }: EventContext & StoreContext): Promise<void> {
@@ -279,12 +406,6 @@ export async function contentNft_AuctionBidCanceled({ event, store }: EventConte
 
   const [memberId, videoId] = new Content.AuctionBidCanceledEvent(event).params
 
-  const announcingPeriodStartedEvent = new AuctionBidCanceledEvent({
-    ...genericEventFields(event),
-  })
-
-  await store.save<AuctionBidCanceledEvent>(announcingPeriodStartedEvent)
-
   // specific event processing
 
   // load video and auction
@@ -306,6 +427,17 @@ export async function contentNft_AuctionBidCanceled({ event, store }: EventConte
 
   // save auction
   await store.save<Auction>(auction)
+
+  // common event processing - second
+
+  const announcingPeriodStartedEvent = new AuctionBidCanceledEvent({
+    ...genericEventFields(event),
+
+    member: new Membership({ id: memberId.toString() }),
+    video,
+  })
+
+  await store.save<AuctionBidCanceledEvent>(announcingPeriodStartedEvent)
 }
 
 export async function contentNft_AuctionCanceled({ event, store }: EventContext & StoreContext): Promise<void> {
@@ -313,12 +445,6 @@ export async function contentNft_AuctionCanceled({ event, store }: EventContext
 
   const [contentActor, videoId] = new Content.AuctionCanceledEvent(event).params
 
-  const announcingPeriodStartedEvent = new AuctionCanceledEvent({
-    ...genericEventFields(event),
-  })
-
-  await store.save<AuctionCanceledEvent>(announcingPeriodStartedEvent)
-
   // specific event processing
 
   // load video and auction
@@ -329,11 +455,25 @@ export async function contentNft_AuctionCanceled({ event, store }: EventContext
     'Non-existing auction got bid canceled'
   )
 
+  // update NFT's transactional status
+  await resetNftTransactionalStatusFromVideo(store, videoId.toString(), `Non-existing NFT's auction canceled`)
+
   // mark auction as canceled
   auction.isCanceled = true
 
   // save auction
   await store.save<Auction>(auction)
+
+  // common event processing - second
+
+  const announcingPeriodStartedEvent = new AuctionCanceledEvent({
+    ...genericEventFields(event),
+
+    contentActor: await convertContentActor(store, contentActor),
+    video,
+  })
+
+  await store.save<AuctionCanceledEvent>(announcingPeriodStartedEvent)
 }
 
 export async function contentNft_EnglishAuctionCompleted({ event, store }: EventContext & StoreContext): Promise<void> {
@@ -341,12 +481,6 @@ export async function contentNft_EnglishAuctionCompleted({ event, store }: Event
 
   const [memberId, videoId] = new Content.EnglishAuctionCompletedEvent(event).params
 
-  const announcingPeriodStartedEvent = new EnglishAuctionCompletedEvent({
-    ...genericEventFields(event),
-  })
-
-  await store.save<EnglishAuctionCompletedEvent>(announcingPeriodStartedEvent)
-
   // specific event processing
 
   // load member
@@ -365,12 +499,26 @@ export async function contentNft_EnglishAuctionCompleted({ event, store }: Event
     'Non-existing english-type auction was completed'
   )
 
+  // update NFT's transactional status
+  await resetNftTransactionalStatusFromVideo(store, videoId.toString(), `Non-existing NFT's auction completed`)
+
   // update auction
   auction.isCompleted = true
   auction.winningMember = member
 
   // save auction
   await store.save<Auction>(auction)
+
+  // common event processing - second
+
+  const announcingPeriodStartedEvent = new EnglishAuctionCompletedEvent({
+    ...genericEventFields(event),
+
+    member,
+    video,
+  })
+
+  await store.save<EnglishAuctionCompletedEvent>(announcingPeriodStartedEvent)
 }
 
 export async function contentNft_BidMadeCompletingAuction({
@@ -381,12 +529,6 @@ export async function contentNft_BidMadeCompletingAuction({
 
   const [memberId, videoId] = new Content.BidMadeCompletingAuctionEvent(event).params
 
-  const announcingPeriodStartedEvent = new BidMadeCompletingAuctionEvent({
-    ...genericEventFields(event),
-  })
-
-  await store.save<BidMadeCompletingAuctionEvent>(announcingPeriodStartedEvent)
-
   // specific event processing
 
   // load member
@@ -405,110 +547,286 @@ export async function contentNft_BidMadeCompletingAuction({
     `Non-existing auction was completed by buy-now bid`
   )
 
+  // update NFT's transactional status
+  await resetNftTransactionalStatusFromVideo(store, videoId.toString(), `Non-existing NFT's auction completed by bid`)
+
   // update auction
   auction.isCompleted = true
   auction.winningMember = member
 
   // save auction
   await store.save<Auction>(auction)
+
+  // common event processing - second
+
+  const announcingPeriodStartedEvent = new BidMadeCompletingAuctionEvent({
+    ...genericEventFields(event),
+
+    member,
+    video,
+  })
+
+  await store.save<BidMadeCompletingAuctionEvent>(announcingPeriodStartedEvent)
 }
 
 export async function contentNft_OpenAuctionBidAccepted({ event, store }: EventContext & StoreContext): Promise<void> {
   // common event processing
 
-  const [contentActor, video] = new Content.OpenAuctionBidAcceptedEvent(event).params
+  const [contentActor, videoId] = new Content.OpenAuctionBidAcceptedEvent(event).params
+
+  // specific event processing
+
+  // load video and auction
+  const { video, auction } = await getAuctionFromVideo(
+    store,
+    videoId.toString(),
+    `Non-existing video's auction accepted a bid`,
+    `Non-existing auction accepted a bid`
+  )
+
+  // ensure member won the auction (only contentActor allowed)
+  const tmpContentActor = await convertContentActor(store, contentActor)
+  if (!(tmpContentActor instanceof ContentActorMember)) {
+    return unexpectedData(`Unexpected content actor. Only Members allowed here.`)
+  }
+  const member = tmpContentActor.member
+
+  // update NFT's transactional status
+  await resetNftTransactionalStatusFromVideo(store, videoId.toString(), `Non-existing NFT's auction completed by bid`)
+
+  // update auction
+  auction.isCompleted = true
+  auction.winningMember = member
+
+  // save auction
+  await store.save<Auction>(auction)
+
+  // common event processing - second
 
   const announcingPeriodStartedEvent = new OpenAuctionBidAcceptedEvent({
     ...genericEventFields(event),
+
+    contentActor: await convertContentActor(store, contentActor),
+    video,
   })
 
   await store.save<OpenAuctionBidAcceptedEvent>(announcingPeriodStartedEvent)
-
-  // specific event processing
-
-  // TODO: what exactly should happen here?
 }
 
 export async function contentNft_OfferStarted({ event, store }: EventContext & StoreContext): Promise<void> {
   // common event processing
 
-  const [video, contentActor, member, price] = new Content.OfferStartedEvent(event).params
+  const [videoId, contentActor, memberId, price] = new Content.OfferStartedEvent(event).params
+
+  // specific event processing
+
+  // load NFT
+  const { video, nft } = await getNftFromVideo(
+    store,
+    videoId.toString(),
+    'Non-existing video was offered',
+    'Non-existing nft was offered'
+  )
+
+  // create offer
+  const transactionalStatus = new TransactionalStatusInitiatedOfferToMember()
+  transactionalStatus.memberId = memberId.toNumber()
+  transactionalStatus.price = price.unwrapOr(undefined)
+
+  // update NFT
+  nft.transactionalStatus = transactionalStatus
+
+  // save NFT
+  await store.save<OwnedNft>(nft)
+
+  // common event processing - second
 
   const announcingPeriodStartedEvent = new OfferStartedEvent({
     ...genericEventFields(event),
+
+    video,
+    contentActor: await convertContentActor(store, contentActor),
+    member: new Membership({ id: memberId.toString() }),
+    price: price.unwrapOr(undefined),
   })
 
   await store.save<OfferStartedEvent>(announcingPeriodStartedEvent)
-
-  // specific event processing
 }
 
 export async function contentNft_OfferAccepted({ event, store }: EventContext & StoreContext): Promise<void> {
   // common event processing
 
-  const [video] = new Content.OfferAcceptedEvent(event).params
+  const [videoId] = new Content.OfferAcceptedEvent(event).params
+
+  // specific event processing
+
+  // load NFT
+  const { video, nft } = await getNftFromVideo(
+    store,
+    videoId.toString(),
+    'Non-existing video sell offer was accepted',
+    'Non-existing nft sell offer was accepted'
+  )
+
+  // read member from offer
+  const memberId = (nft.transactionalStatus as TransactionalStatusInitiatedOfferToMember).memberId
+  const member = new Membership({ id: memberId.toString() })
+
+  // update NFT
+  nft.transactionalStatus = new TransactionalStatusIdle()
+  nft.ownerMember = member
+
+  // save NFT
+  await store.save<OwnedNft>(nft)
+
+  // common event processing - second
 
   const announcingPeriodStartedEvent = new OfferAcceptedEvent({
     ...genericEventFields(event),
+
+    video,
   })
 
   await store.save<OfferAcceptedEvent>(announcingPeriodStartedEvent)
-
-  // specific event processing
 }
 
 export async function contentNft_OfferCanceled({ event, store }: EventContext & StoreContext): Promise<void> {
   // common event processing
 
-  const [video, contentActor] = new Content.OfferCanceledEvent(event).params
+  const [videoId, contentActor] = new Content.OfferCanceledEvent(event).params
+
+  // specific event processing
+
+  // load NFT
+  const { video, nft } = await getNftFromVideo(
+    store,
+    videoId.toString(),
+    'Non-existing video sell offer was canceled',
+    'Non-existing nft sell offer was canceled'
+  )
+
+  // update NFT
+  nft.transactionalStatus = new TransactionalStatusIdle()
+
+  // save NFT
+  await store.save<OwnedNft>(nft)
+
+  // common event processing - second
 
   const announcingPeriodStartedEvent = new OfferCanceledEvent({
     ...genericEventFields(event),
+
+    video,
+    contentActor: await convertContentActor(store, contentActor),
   })
 
   await store.save<OfferCanceledEvent>(announcingPeriodStartedEvent)
-
-  // specific event processing
 }
 
 export async function contentNft_NftSellOrderMade({ event, store }: EventContext & StoreContext): Promise<void> {
   // common event processing
 
-  const [video, contentActor, price] = new Content.NFTSellOrderMadeEvent(event).params
+  const [videoId, contentActor, price] = new Content.NFTSellOrderMadeEvent(event).params
+
+  // specific event processing
+
+  // load NFT
+  const { video, nft } = await getNftFromVideo(
+    store,
+    videoId.toString(),
+    'Non-existing video was offered',
+    'Non-existing nft was offered'
+  )
+
+  // create buy now offer
+  const transactionalStatus = new TransactionalStatusBuyNow()
+  transactionalStatus.price = price
+
+  // update NFT
+  nft.transactionalStatus = transactionalStatus
+
+  // save NFT
+  await store.save<OwnedNft>(nft)
+
+  // common event processing - second
 
   const announcingPeriodStartedEvent = new NftSellOrderMadeEvent({
     ...genericEventFields(event),
+
+    video,
+    contentActor: await convertContentActor(store, contentActor),
+    price,
   })
 
   await store.save<NftSellOrderMadeEvent>(announcingPeriodStartedEvent)
-
-  // specific event processing
 }
 
 export async function contentNft_NftBought({ event, store }: EventContext & StoreContext): Promise<void> {
   // common event processing
 
-  const [video, member] = new Content.NFTBoughtEvent(event).params
+  const [videoId, memberId] = new Content.NFTBoughtEvent(event).params
+
+  // specific event processing
+
+  // load NFT
+  const { video, nft } = await getNftFromVideo(
+    store,
+    videoId.toString(),
+    'Non-existing video was bought',
+    'Non-existing nft was bought'
+  )
+
+  // read member
+  const member = new Membership({ id: memberId.toString() })
+
+  // update NFT
+  nft.transactionalStatus = new TransactionalStatusIdle()
+  nft.ownerMember = member
+
+  // save NFT
+  await store.save<OwnedNft>(nft)
+
+  // common event processing - second
 
   const announcingPeriodStartedEvent = new NftBoughtEvent({
     ...genericEventFields(event),
+
+    video,
+    member,
   })
 
   await store.save<NftBoughtEvent>(announcingPeriodStartedEvent)
-
-  // specific event processing
 }
 
 export async function contentNft_BuyNowCanceled({ event, store }: EventContext & StoreContext): Promise<void> {
   // common event processing
 
-  const [video, contentActor] = new Content.BuyNowCanceledEvent(event).params
+  const [videoId, contentActor] = new Content.BuyNowCanceledEvent(event).params
+
+  // specific event processing
+
+  // load NFT
+  const { video, nft } = await getNftFromVideo(
+    store,
+    videoId.toString(),
+    'Non-existing video was bought',
+    'Non-existing nft was bought'
+  )
+
+  // update NFT
+  nft.transactionalStatus = new TransactionalStatusIdle()
+
+  // save NFT
+  await store.save<OwnedNft>(nft)
+
+  // common event processing - second
 
   const announcingPeriodStartedEvent = new BuyNowCanceledEvent({
     ...genericEventFields(event),
+
+    video,
+    contentActor: await convertContentActor(store, contentActor),
   })
 
   await store.save<BuyNowCanceledEvent>(announcingPeriodStartedEvent)
-
-  // specific event processing
 }

+ 2 - 2
query-node/schemas/contentNft.graphql

@@ -90,7 +90,7 @@ type TransactionalStatusIdle @variant {
 "Represents TransactionalStatus InitiatedOfferToMember"
 type TransactionalStatusInitiatedOfferToMember @variant {
   "Member identifier"
-  member: Int!
+  memberId: Int!
 
   "Whether member should pay to accept offer (optional)"
   price: BigInt
@@ -107,7 +107,7 @@ type TransactionalStatusAuction @variant {
 
 "Represents TransactionalStatus BuyNow"
 type TransactionalStatusBuyNow @variant {
-  price: Int!
+  price: BigInt!
 }
 
 "Represents various action types"

+ 77 - 81
query-node/schemas/contentNftEvents.graphql

@@ -1,20 +1,16 @@
-# TODO: add `implements Event @entity` to events
-# remove relations in events and save snapshot representation (immutable)
-# TODO: unite leading dot `.` in property descriptions
-
 type AuctionStartedEvent implements Event @entity {
   ### GENERIC DATA ###
 
-  "(network}-{blockNumber}-{indexInBlock}"
+  "(network}-{blockNumber}-{indexInBlock}."
   id: ID!
 
-  "Hash of the extrinsic which caused the event to be emitted"
+  "Hash of the extrinsic which caused the event to be emitted."
   inExtrinsic: String
 
   "Blocknumber of the block in which the event was emitted."
   inBlock: Int!
 
-  "Network the block was produced in"
+  "Network the block was produced in."
   network: Network!
 
   "Index of event in block from which it was emitted."
@@ -22,29 +18,29 @@ type AuctionStartedEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "Actor that started this auction"
+  "Actor that started this auction."
   actor: ContentActor!
 
-  "Video that's being auctioned"
+  "Video that's being auctioned."
   video: Video!
 
-  "Auction started"
+  "Auction started."
   auction: Auction!
 }
 
 type NftIssuedEvent implements Event @entity {
   ### GENERIC DATA ###
 
-  "(network}-{blockNumber}-{indexInBlock}"
+  "(network}-{blockNumber}-{indexInBlock}."
   id: ID!
 
-  "Hash of the extrinsic which caused the event to be emitted"
+  "Hash of the extrinsic which caused the event to be emitted."
   inExtrinsic: String
 
   "Blocknumber of the block in which the event was emitted."
   inBlock: Int!
 
-  "Network the block was produced in"
+  "Network the block was produced in."
   network: Network!
 
   "Index of event in block from which it was emitted."
@@ -52,36 +48,36 @@ type NftIssuedEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "Content actor that issued the NFT"
+  "Content actor that issued the NFT."
   contentActor: ContentActor!
 
-  "Video represented via NFT"
+  "Video represented via NFT."
   video: Video!
 
-  "Royalty for the NFT/video"
+  "Royalty for the NFT/video."
   royalty: Float
 
   # TODO: inspect if metadata can be unpacked and mean something useful
-  "NFT's metadata"
+  "NFT's metadata."
   metadata: String!
 
-  "Member NFT was originally issued to"
+  "Member NFT was originally issued to."
   newOwner: Membership
 }
 
 type AuctionBidMadeEvent implements Event @entity {
   ### GENERIC DATA ###
 
-  "(network}-{blockNumber}-{indexInBlock}"
+  "(network}-{blockNumber}-{indexInBlock}."
   id: ID!
 
-  "Hash of the extrinsic which caused the event to be emitted"
+  "Hash of the extrinsic which caused the event to be emitted."
   inExtrinsic: String
 
   "Blocknumber of the block in which the event was emitted."
   inBlock: Int!
 
-  "Network the block was produced in"
+  "Network the block was produced in."
   network: Network!
 
   "Index of event in block from which it was emitted."
@@ -92,29 +88,29 @@ type AuctionBidMadeEvent implements Event @entity {
   "Member bidding in the auction."
   member: Membership!
 
-  "Video that's bidden on"
+  "Video that's bidden on."
   video: Video!
 
-  "Bid made"
+  "Bid made."
   bidAmount: BigInt!
 
-  "Sign of auction duration being extended by making this bid"
+  "Sign of auction duration being extended by making this bid."
   extendsAuction: Boolean!
 }
 
 type AuctionBidCanceledEvent implements Event @entity {
   ### GENERIC DATA ###
 
-  "(network}-{blockNumber}-{indexInBlock}"
+  "(network}-{blockNumber}-{indexInBlock}."
   id: ID!
 
-  "Hash of the extrinsic which caused the event to be emitted"
+  "Hash of the extrinsic which caused the event to be emitted."
   inExtrinsic: String
 
   "Blocknumber of the block in which the event was emitted."
   inBlock: Int!
 
-  "Network the block was produced in"
+  "Network the block was produced in."
   network: Network!
 
   "Index of event in block from which it was emitted."
@@ -122,26 +118,26 @@ type AuctionBidCanceledEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "Auction that canceled the bid"
+  "Auction that canceled the bid."
   member: Membership!
 
-  "Auctioned video"
+  "Auctioned video."
   video: Video!
 }
 
 type AuctionCanceledEvent implements Event @entity {
   ### GENERIC DATA ###
 
-  "(network}-{blockNumber}-{indexInBlock}"
+  "(network}-{blockNumber}-{indexInBlock}."
   id: ID!
 
-  "Hash of the extrinsic which caused the event to be emitted"
+  "Hash of the extrinsic which caused the event to be emitted."
   inExtrinsic: String
 
   "Blocknumber of the block in which the event was emitted."
   inBlock: Int!
 
-  "Network the block was produced in"
+  "Network the block was produced in."
   network: Network!
 
   "Index of event in block from which it was emitted."
@@ -149,26 +145,26 @@ type AuctionCanceledEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "Content actor canceling the event"
+  "Content actor canceling the event."
   contentActor: ContentActor!
 
-  "Auctioned video"
+  "Auctioned video."
   video: Video!
 }
 
 type EnglishAuctionCompletedEvent implements Event @entity {
   ### GENERIC DATA ###
 
-  "(network}-{blockNumber}-{indexInBlock}"
+  "(network}-{blockNumber}-{indexInBlock}."
   id: ID!
 
-  "Hash of the extrinsic which caused the event to be emitted"
+  "Hash of the extrinsic which caused the event to be emitted."
   inExtrinsic: String
 
   "Blocknumber of the block in which the event was emitted."
   inBlock: Int!
 
-  "Network the block was produced in"
+  "Network the block was produced in."
   network: Network!
 
   "Index of event in block from which it was emitted."
@@ -176,26 +172,26 @@ type EnglishAuctionCompletedEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "Member claiming the auctioned NFT"
+  "Member claiming the auctioned NFT."
   member: Membership!
 
-  "Auctioned video"
+  "Auctioned video."
   video: Video!
 }
 
 type BidMadeCompletingAuctionEvent implements Event @entity {
   ### GENERIC DATA ###
 
-  "(network}-{blockNumber}-{indexInBlock}"
+  "(network}-{blockNumber}-{indexInBlock}."
   id: ID!
 
-  "Hash of the extrinsic which caused the event to be emitted"
+  "Hash of the extrinsic which caused the event to be emitted."
   inExtrinsic: String
 
   "Blocknumber of the block in which the event was emitted."
   inBlock: Int!
 
-  "Network the block was produced in"
+  "Network the block was produced in."
   network: Network!
 
   "Index of event in block from which it was emitted."
@@ -203,26 +199,26 @@ type BidMadeCompletingAuctionEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "Member completing the auction"
+  "Member completing the auction."
   member: Membership!
 
-  "Auctioned video"
+  "Auctioned video."
   video: Video!
 }
 
 type OpenAuctionBidAcceptedEvent implements Event @entity {
   ### GENERIC DATA ###
 
-  "(network}-{blockNumber}-{indexInBlock}"
+  "(network}-{blockNumber}-{indexInBlock}."
   id: ID!
 
-  "Hash of the extrinsic which caused the event to be emitted"
+  "Hash of the extrinsic which caused the event to be emitted."
   inExtrinsic: String
 
   "Blocknumber of the block in which the event was emitted."
   inBlock: Int!
 
-  "Network the block was produced in"
+  "Network the block was produced in."
   network: Network!
 
   "Index of event in block from which it was emitted."
@@ -230,26 +226,26 @@ type OpenAuctionBidAcceptedEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "Content actor canceling the event"
+  "Content actor canceling the event."
   contentActor: ContentActor!
 
-  "Auctioned video"
+  "Auctioned video."
   video: Video!
 }
 
 type OfferStartedEvent implements Event @entity {
   ### GENERIC DATA ###
 
-  "(network}-{blockNumber}-{indexInBlock}"
+  "(network}-{blockNumber}-{indexInBlock}."
   id: ID!
 
-  "Hash of the extrinsic which caused the event to be emitted"
+  "Hash of the extrinsic which caused the event to be emitted."
   inExtrinsic: String
 
   "Blocknumber of the block in which the event was emitted."
   inBlock: Int!
 
-  "Network the block was produced in"
+  "Network the block was produced in."
   network: Network!
 
   "Index of event in block from which it was emitted."
@@ -257,32 +253,32 @@ type OfferStartedEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "NFT's video"
+  "NFT's video."
   video: Video!
 
-  "Content actor acting as NFT owner"
+  "Content actor acting as NFT owner."
   contentActor: ContentActor!
 
-  "Member that receives the offer"
+  "Member that receives the offer."
   member: Membership!
 
-  "Offer's price"
+  "Offer's price."
   price: BigInt
 }
 
 type OfferAcceptedEvent implements Event @entity {
   ### GENERIC DATA ###
 
-  "(network}-{blockNumber}-{indexInBlock}"
+  "(network}-{blockNumber}-{indexInBlock}."
   id: ID!
 
-  "Hash of the extrinsic which caused the event to be emitted"
+  "Hash of the extrinsic which caused the event to be emitted."
   inExtrinsic: String
 
   "Blocknumber of the block in which the event was emitted."
   inBlock: Int!
 
-  "Network the block was produced in"
+  "Network the block was produced in."
   network: Network!
 
   "Index of event in block from which it was emitted."
@@ -290,23 +286,23 @@ type OfferAcceptedEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "NFT's video"
+  "NFT's video."
   video: Video!
 }
 
 type OfferCanceledEvent implements Event @entity {
   ### GENERIC DATA ###
 
-  "(network}-{blockNumber}-{indexInBlock}"
+  "(network}-{blockNumber}-{indexInBlock}."
   id: ID!
 
-  "Hash of the extrinsic which caused the event to be emitted"
+  "Hash of the extrinsic which caused the event to be emitted."
   inExtrinsic: String
 
   "Blocknumber of the block in which the event was emitted."
   inBlock: Int!
 
-  "Network the block was produced in"
+  "Network the block was produced in."
   network: Network!
 
   "Index of event in block from which it was emitted."
@@ -314,26 +310,26 @@ type OfferCanceledEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "NFT's video"
+  "NFT's video."
   video: Video!
 
-  "Content actor acting as NFT owner"
+  "Content actor acting as NFT owner."
   contentActor: ContentActor!
 }
 
 type NftSellOrderMadeEvent @entity { # NFT in name can't be UPPERCASE because it causes codegenimplements Event  errors
   ### GENERIC DATA ###
 
-  "(network}-{blockNumber}-{indexInBlock}"
+  "(network}-{blockNumber}-{indexInBlock}."
   id: ID!
 
-  "Hash of the extrinsic which caused the event to be emitted"
+  "Hash of the extrinsic which caused the event to be emitted."
   inExtrinsic: String
 
   "Blocknumber of the block in which the event was emitted."
   inBlock: Int!
 
-  "Network the block was produced in"
+  "Network the block was produced in."
   network: Network!
 
   "Index of event in block from which it was emitted."
@@ -341,29 +337,29 @@ type NftSellOrderMadeEvent @entity { # NFT in name can't be UPPERCASE because it
 
   ### SPECIFIC DATA ###
 
-  "NFT's video"
+  "NFT's video."
   video: Video!
 
-  "Content actor acting as NFT owner"
+  "Content actor acting as NFT owner."
   contentActor: ContentActor!
 
-  "Offer's price"
+  "Offer's price."
   price: BigInt!
 }
 
 type NftBoughtEvent implements Event @entity {
   ### GENERIC DATA ###
 
-  "(network}-{blockNumber}-{indexInBlock}"
+  "(network}-{blockNumber}-{indexInBlock}."
   id: ID!
 
-  "Hash of the extrinsic which caused the event to be emitted"
+  "Hash of the extrinsic which caused the event to be emitted."
   inExtrinsic: String
 
   "Blocknumber of the block in which the event was emitted."
   inBlock: Int!
 
-  "Network the block was produced in"
+  "Network the block was produced in."
   network: Network!
 
   "Index of event in block from which it was emitted."
@@ -371,26 +367,26 @@ type NftBoughtEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "NFT's video"
+  "NFT's video."
   video: Video!
 
-  "Member that bought the NFT"
+  "Member that bought the NFT."
   member: Membership!
 }
 
 type BuyNowCanceledEvent implements Event @entity {
   ### GENERIC DATA ###
 
-  "(network}-{blockNumber}-{indexInBlock}"
+  "(network}-{blockNumber}-{indexInBlock}."
   id: ID!
 
-  "Hash of the extrinsic which caused the event to be emitted"
+  "Hash of the extrinsic which caused the event to be emitted."
   inExtrinsic: String
 
   "Blocknumber of the block in which the event was emitted."
   inBlock: Int!
 
-  "Network the block was produced in"
+  "Network the block was produced in."
   network: Network!
 
   "Index of event in block from which it was emitted."
@@ -398,9 +394,9 @@ type BuyNowCanceledEvent implements Event @entity {
 
   ### SPECIFIC DATA ###
 
-  "NFT's video"
+  "NFT's video."
   video: Video!
 
-  "Content actor acting as NFT owner"
+  "Content actor acting as NFT owner."
   contentActor: ContentActor!
 }