Browse Source

query node - NFT issuance mappings update II

ondratra 3 years ago
parent
commit
eb5a34e1da

+ 6 - 2
query-node/mappings/src/content/nft.ts

@@ -433,8 +433,12 @@ export async function convertTransactionalStatus(
 
   if (transactionalStatus.isAuction) {
     const auctionParams = transactionalStatus.asAuction
+
+    // create new auction
+    const auction = await createAuction(store, nft, auctionParams, blockNumber)
+
     const status = new TransactionalStatusAuction()
-    status.auction = await createAuction(store, nft, auctionParams, blockNumber)
+    status.auctionId = auction.id
 
     return status
   }
@@ -843,7 +847,7 @@ export async function contentNft_NftSellOrderMade({ event, store }: EventContext
 
   // update NFT transactional status
   const transactionalStatus = new TransactionalStatusBuyNow()
-  transactionalStatus.price = price
+  transactionalStatus.price = new BN(price.toString())
   await setNewNftTransactionalStatus(store, nft, transactionalStatus, event.blockNumber)
 
   // common event processing - second

+ 15 - 9
tests/integration-tests/src/Api.ts

@@ -948,40 +948,46 @@ export class Api {
     return await this.sender.signAndSend(this.api.tx.content.claimWonEnglishAuction(memberId, videoId), accountFrom)
   }
 
-  async pickOpenAuctionWinner(accountFrom: string, memberId: number, videoId: number) {
+  async pickOpenAuctionWinner(accountFrom: string, memberId: number, videoId: number): Promise<ISubmittableResult> {
     return await this.sender.signAndSend(
       this.api.tx.content.pickOpenAuctionWinner({ Member: memberId }, videoId),
       accountFrom
     )
   }
 
-  async cancelOpenAuctionBid(accountFrom: string, participantId: number, videoId: number) {
+  async cancelOpenAuctionBid(accountFrom: string, participantId: number, videoId: number): Promise<ISubmittableResult> {
     return await this.sender.signAndSend(this.api.tx.content.cancelOpenAuctionBid(participantId, videoId), accountFrom)
   }
 
-  async cancelNftAuction(accountFrom: string, ownerId: number, videoId: number) {
+  async cancelNftAuction(accountFrom: string, ownerId: number, videoId: number): Promise<ISubmittableResult> {
     return await this.sender.signAndSend(
       this.api.tx.content.cancelNftAuction({ Member: ownerId }, videoId),
       accountFrom
     )
   }
 
-  async sellNft(accountFrom: string, videoId: number, ownerId: number, price: BN) {
+  async sellNft(accountFrom: string, videoId: number, ownerId: number, price: BN): Promise<ISubmittableResult> {
     return await this.sender.signAndSend(this.api.tx.content.sellNft(videoId, { Member: ownerId }, price), accountFrom)
   }
 
-  async buyNft(accountFrom: string, videoId: number, participantId: number) {
+  async buyNft(accountFrom: string, videoId: number, participantId: number): Promise<ISubmittableResult> {
     return await this.sender.signAndSend(this.api.tx.content.buyNft(videoId, participantId), accountFrom)
   }
 
-  async offerNft(accountFrom: string, videoId: number, ownerId: number, toMemberId: number, price: BN | null = null) {
+  async offerNft(
+    accountFrom: string,
+    videoId: number,
+    ownerId: number,
+    toMemberId: number,
+    price: BN | null = null
+  ): Promise<ISubmittableResult> {
     return await this.sender.signAndSend(
       this.api.tx.content.offerNft(videoId, { Member: ownerId }, toMemberId, price),
       accountFrom
     )
   }
 
-  async acceptIncomingOffer(accountFrom: string, videoId: number) {
+  async acceptIncomingOffer(accountFrom: string, videoId: number): Promise<ISubmittableResult> {
     return await this.sender.signAndSend(this.api.tx.content.acceptIncomingOffer(videoId), accountFrom)
   }
 
@@ -990,7 +996,7 @@ export class Api {
     ownerId: number,
     channeld: number,
     auctionParams: AuctionParams
-  ) {
+  ): Promise<ISubmittableResult> {
     const createParameters = this.createType('VideoCreationParameters', {
       assets: null,
       meta: null,
@@ -998,7 +1004,7 @@ export class Api {
       auto_issue_nft: this.api.createType('NftIssuanceParameters', {
         royalty: null,
         nft_metadata: this.api.createType('NftMetadata', '').toU8a(),
-        non_channel_owner: null,
+        non_channel_owner: ownerId,
         init_transactional_status: this.api.createType('InitTransactionalStatus', { Auction: auctionParams }),
       }),
     })

+ 9 - 0
tests/integration-tests/src/cli/base.ts

@@ -2,6 +2,7 @@ import path from 'path'
 import { execFile, ChildProcess, PromiseWithChild, ExecFileException, ExecException } from 'child_process'
 import { promisify } from 'util'
 import { Sender } from '../sender'
+import { debuggingCli } from '../consts'
 
 export type CommandResult = {
   exitCode: number
@@ -58,6 +59,14 @@ export abstract class CLI {
       lockKeys.map((k) => `nonce-${k}`),
 
       async () => {
+        if (debuggingCli) {
+          console.log(
+            'Running CLI command: ',
+            `AUTO_CONFIRM=true HOME="${env.HOME}"`,
+            this.binPath,
+            [command, ...this.getArgs(customArgs)].join(' ')
+          )
+        }
         try {
           // execute command and wait for std outputs (or error)
           const execOutputs = await pExecFile(this.binPath, [command, ...this.getArgs(customArgs)], {

+ 2 - 2
tests/integration-tests/src/cli/joystream.ts

@@ -93,9 +93,9 @@ export class JoystreamCLI extends CLI {
     Selects active member for CLI commands.
   */
   async chooseMemberAccount(memberId: MemberId) {
-    const { stderr } = await this.run('membership:chooseMember', ['--memberId', memberId.toString()])
+    const { stderr, exitCode } = await this.run('membership:chooseMember', ['--memberId', memberId.toString()])
 
-    if (stderr && !stderr.match(/^\s*Member switched to id/)) {
+    if (exitCode && !stderr.match(/^\s*Member switched to id/)) {
       throw new Error(`Unexpected CLI failure on choosing account: "${stderr}"`)
     }
   }

+ 6 - 3
tests/integration-tests/src/cli/utils.ts

@@ -6,6 +6,7 @@ import { Utils } from '../utils'
 import _ from 'lodash'
 import bmp from 'bmp-js'
 import nodeCleanup from 'node-cleanup'
+import { debuggingCli } from '../consts'
 
 export class TmpFileManager {
   tmpDataDir: string
@@ -17,9 +18,11 @@ export class TmpFileManager {
       uuid()
     )
     mkdirSync(this.tmpDataDir, { recursive: true })
-    nodeCleanup(() => {
-      rmSync(this.tmpDataDir, { recursive: true, force: true })
-    })
+    if (!debuggingCli) {
+      nodeCleanup(() => {
+        rmSync(this.tmpDataDir, { recursive: true, force: true })
+      })
+    }
   }
 
   public jsonFile(value: unknown): string {

+ 2 - 0
tests/integration-tests/src/consts.ts

@@ -3,6 +3,8 @@ import { AugmentedConsts } from '@polkadot/api/types'
 import BN from 'bn.js'
 import { ProposalType, WorkingGroupModuleName } from './types'
 
+export const debuggingCli = false // set to true to see CLI commands run
+
 // Dummy const type validation function (see: https://stackoverflow.com/questions/57069802/as-const-is-ignored-when-there-is-a-type-definition)
 export const validateType = <T>(obj: T) => obj
 

+ 4 - 1
tests/integration-tests/src/fixtures/content/nft/createVideoWithAuction.ts

@@ -6,6 +6,7 @@ import { IMember } from '../createMembers'
 import { PlaceBidsInAuctionFixture } from './placeBidsInAuction'
 import BN from 'bn.js'
 import { assertNftOwner } from './utils'
+import { assert } from 'chai'
 
 export class NftCreateVideoWithAuctionFixture extends BaseQueryNodeFixture {
   private cli: JoystreamCLI
@@ -34,10 +35,12 @@ export class NftCreateVideoWithAuctionFixture extends BaseQueryNodeFixture {
       this.channelId,
       auctionParams
     )
+
     const event = await this.api.retrieveVideoCreatedEventDetails(response)
 
+    this.debug('Check NFT ownership change')
     await assertNftOwner(this.query, event.videoId.toNumber(), this.author, (ownedNft) => {
-      // TODO: assert transactional status
+      assert.equal(ownedNft.transactionalStatus.__typename, 'TransactionalStatusAuction')
     })
   }
 }

+ 1 - 2
tests/integration-tests/src/flows/content/nftAuctionAndOffers.ts

@@ -94,11 +94,10 @@ export default async function nftAuctionAndOffers({ api, query, env }: FlowProps
 
   await new FixtureRunner(openAuctionFixture).run()
 
-  /* TODO: fix this - QN doesn't catch the events for buy-know from unkown reason
   const nftBuyNowFixture = new NftBuyNowFixture(api, query, joystreamCli, nextVideo().videoId, author as IMember, auctionParticipants[0])
 
   await new FixtureRunner(nftBuyNowFixture).run()
-*/
+
   const nftDirectOfferFixture = new NftDirectOfferFixture(
     api,
     query,

+ 8 - 0
tests/integration-tests/src/graphql/generated/queries.ts

@@ -13,6 +13,11 @@ export type OwnedNftFieldsFragment = {
   creatorRoyalty?: Types.Maybe<number>
   video: { id: string }
   ownerMember?: Types.Maybe<{ id: string }>
+  transactionalStatus:
+    | { __typename: 'TransactionalStatusIdle' }
+    | { __typename: 'TransactionalStatusInitiatedOfferToMember' }
+    | { __typename: 'TransactionalStatusAuction' }
+    | { __typename: 'TransactionalStatusBuyNow' }
 }
 
 export type GetChannelsQueryVariables = Types.Exact<{ [key: string]: never }>
@@ -1960,6 +1965,9 @@ export const OwnedNftFields = gql`
       id
     }
     metadata
+    transactionalStatus {
+      __typename
+    }
     creatorRoyalty
   }
 `

+ 124 - 14
tests/integration-tests/src/graphql/generated/schema.ts

@@ -655,8 +655,8 @@ export type Auction = BaseGraphQlObject & {
   version: Scalars['Int']
   nft: OwnedNft
   nftId: Scalars['String']
-  initialOwner: Membership
-  initialOwnerId: Scalars['String']
+  initialOwner?: Maybe<Membership>
+  initialOwnerId?: Maybe<Scalars['String']>
   winningMember?: Maybe<Membership>
   winningMemberId?: Maybe<Scalars['String']>
   /** Auction starting price */
@@ -1100,7 +1100,7 @@ export type AuctionConnection = {
 
 export type AuctionCreateInput = {
   nft: Scalars['ID']
-  initialOwner: Scalars['ID']
+  initialOwner?: Maybe<Scalars['ID']>
   winningMember?: Maybe<Scalars['ID']>
   startingPrice: Scalars['String']
   buyNowPrice?: Maybe<Scalars['String']>
@@ -4684,7 +4684,6 @@ export type CuratorGroup = BaseGraphQlObject & {
   isActive: Scalars['Boolean']
   curators: Array<Curator>
   channels: Array<Channel>
-  ownednftownerCuratorGroup?: Maybe<Array<OwnedNft>>
 }
 
 export type CuratorGroupConnection = {
@@ -4750,9 +4749,6 @@ export type CuratorGroupWhereInput = {
   channels_none?: Maybe<ChannelWhereInput>
   channels_some?: Maybe<ChannelWhereInput>
   channels_every?: Maybe<ChannelWhereInput>
-  ownednftownerCuratorGroup_none?: Maybe<OwnedNftWhereInput>
-  ownednftownerCuratorGroup_some?: Maybe<OwnedNftWhereInput>
-  ownednftownerCuratorGroup_every?: Maybe<OwnedNftWhereInput>
   AND?: Maybe<Array<CuratorGroupWhereInput>>
   OR?: Maybe<Array<CuratorGroupWhereInput>>
 }
@@ -12277,12 +12273,11 @@ export type OwnedNft = BaseGraphQlObject & {
   auctions: Array<Auction>
   ownerMember?: Maybe<Membership>
   ownerMemberId?: Maybe<Scalars['String']>
-  ownerCuratorGroup?: Maybe<CuratorGroup>
-  ownerCuratorGroupId?: Maybe<Scalars['String']>
   /** NFT's metadata */
   metadata: Scalars['String']
   /** NFT transactional status */
   transactionalStatus: TransactionalStatus
+  transactionalStatusUpdates: Array<TransactionalStatusUpdate>
   /** Creator royalty */
   creatorRoyalty?: Maybe<Scalars['Float']>
 }
@@ -12295,7 +12290,6 @@ export type OwnedNftConnection = {
 
 export type OwnedNftCreateInput = {
   ownerMember?: Maybe<Scalars['ID']>
-  ownerCuratorGroup?: Maybe<Scalars['ID']>
   metadata: Scalars['String']
   transactionalStatus: Scalars['JSONObject']
   creatorRoyalty?: Maybe<Scalars['Float']>
@@ -12315,8 +12309,6 @@ export enum OwnedNftOrderByInput {
   DeletedAtDesc = 'deletedAt_DESC',
   OwnerMemberAsc = 'ownerMember_ASC',
   OwnerMemberDesc = 'ownerMember_DESC',
-  OwnerCuratorGroupAsc = 'ownerCuratorGroup_ASC',
-  OwnerCuratorGroupDesc = 'ownerCuratorGroup_DESC',
   MetadataAsc = 'metadata_ASC',
   MetadataDesc = 'metadata_DESC',
   CreatorRoyaltyAsc = 'creatorRoyalty_ASC',
@@ -12325,7 +12317,6 @@ export enum OwnedNftOrderByInput {
 
 export type OwnedNftUpdateInput = {
   ownerMember?: Maybe<Scalars['ID']>
-  ownerCuratorGroup?: Maybe<Scalars['ID']>
   metadata?: Maybe<Scalars['String']>
   transactionalStatus?: Maybe<Scalars['JSONObject']>
   creatorRoyalty?: Maybe<Scalars['Float']>
@@ -12373,7 +12364,9 @@ export type OwnedNftWhereInput = {
   auctions_some?: Maybe<AuctionWhereInput>
   auctions_every?: Maybe<AuctionWhereInput>
   ownerMember?: Maybe<MembershipWhereInput>
-  ownerCuratorGroup?: Maybe<CuratorGroupWhereInput>
+  transactionalStatusUpdates_none?: Maybe<TransactionalStatusUpdateWhereInput>
+  transactionalStatusUpdates_some?: Maybe<TransactionalStatusUpdateWhereInput>
+  transactionalStatusUpdates_every?: Maybe<TransactionalStatusUpdateWhereInput>
   AND?: Maybe<Array<OwnedNftWhereInput>>
   OR?: Maybe<Array<OwnedNftWhereInput>>
 }
@@ -15610,6 +15603,9 @@ export type Query = {
   threadMovedEvents: Array<ThreadMovedEvent>
   threadMovedEventByUniqueInput?: Maybe<ThreadMovedEvent>
   threadMovedEventsConnection: ThreadMovedEventConnection
+  transactionalStatusUpdates: Array<TransactionalStatusUpdate>
+  transactionalStatusUpdateByUniqueInput?: Maybe<TransactionalStatusUpdate>
+  transactionalStatusUpdatesConnection: TransactionalStatusUpdateConnection
   upcomingWorkingGroupOpenings: Array<UpcomingWorkingGroupOpening>
   upcomingWorkingGroupOpeningByUniqueInput?: Maybe<UpcomingWorkingGroupOpening>
   upcomingWorkingGroupOpeningsConnection: UpcomingWorkingGroupOpeningConnection
@@ -18529,6 +18525,26 @@ export type QueryThreadMovedEventsConnectionArgs = {
   orderBy?: Maybe<Array<ThreadMovedEventOrderByInput>>
 }
 
+export type QueryTransactionalStatusUpdatesArgs = {
+  offset?: Maybe<Scalars['Int']>
+  limit?: Maybe<Scalars['Int']>
+  where?: Maybe<TransactionalStatusUpdateWhereInput>
+  orderBy?: Maybe<Array<TransactionalStatusUpdateOrderByInput>>
+}
+
+export type QueryTransactionalStatusUpdateByUniqueInputArgs = {
+  where: TransactionalStatusUpdateWhereUniqueInput
+}
+
+export type QueryTransactionalStatusUpdatesConnectionArgs = {
+  first?: Maybe<Scalars['Int']>
+  after?: Maybe<Scalars['String']>
+  last?: Maybe<Scalars['Int']>
+  before?: Maybe<Scalars['String']>
+  where?: Maybe<TransactionalStatusUpdateWhereInput>
+  orderBy?: Maybe<Array<TransactionalStatusUpdateOrderByInput>>
+}
+
 export type QueryUpcomingWorkingGroupOpeningsArgs = {
   offset?: Maybe<Scalars['Int']>
   limit?: Maybe<Scalars['Int']>
@@ -23236,6 +23252,100 @@ export type TransactionalStatusInitiatedOfferToMember = {
   price?: Maybe<Scalars['Float']>
 }
 
+export type TransactionalStatusUpdate = BaseGraphQlObject & {
+  id: Scalars['ID']
+  createdAt: Scalars['DateTime']
+  createdById: Scalars['String']
+  updatedAt?: Maybe<Scalars['DateTime']>
+  updatedById?: Maybe<Scalars['String']>
+  deletedAt?: Maybe<Scalars['DateTime']>
+  deletedById?: Maybe<Scalars['String']>
+  version: Scalars['Int']
+  nft: OwnedNft
+  nftId: Scalars['String']
+  /** NFT transactional status */
+  transactionalStatus: TransactionalStatus
+  /** Block number at which change happened */
+  changedAt: Scalars['Int']
+}
+
+export type TransactionalStatusUpdateConnection = {
+  totalCount: Scalars['Int']
+  edges: Array<TransactionalStatusUpdateEdge>
+  pageInfo: PageInfo
+}
+
+export type TransactionalStatusUpdateCreateInput = {
+  nft: Scalars['ID']
+  transactionalStatus: Scalars['JSONObject']
+  changedAt: Scalars['Float']
+}
+
+export type TransactionalStatusUpdateEdge = {
+  node: TransactionalStatusUpdate
+  cursor: Scalars['String']
+}
+
+export enum TransactionalStatusUpdateOrderByInput {
+  CreatedAtAsc = 'createdAt_ASC',
+  CreatedAtDesc = 'createdAt_DESC',
+  UpdatedAtAsc = 'updatedAt_ASC',
+  UpdatedAtDesc = 'updatedAt_DESC',
+  DeletedAtAsc = 'deletedAt_ASC',
+  DeletedAtDesc = 'deletedAt_DESC',
+  NftAsc = 'nft_ASC',
+  NftDesc = 'nft_DESC',
+  ChangedAtAsc = 'changedAt_ASC',
+  ChangedAtDesc = 'changedAt_DESC',
+}
+
+export type TransactionalStatusUpdateUpdateInput = {
+  nft?: Maybe<Scalars['ID']>
+  transactionalStatus?: Maybe<Scalars['JSONObject']>
+  changedAt?: Maybe<Scalars['Float']>
+}
+
+export type TransactionalStatusUpdateWhereInput = {
+  id_eq?: Maybe<Scalars['ID']>
+  id_in?: Maybe<Array<Scalars['ID']>>
+  createdAt_eq?: Maybe<Scalars['DateTime']>
+  createdAt_lt?: Maybe<Scalars['DateTime']>
+  createdAt_lte?: Maybe<Scalars['DateTime']>
+  createdAt_gt?: Maybe<Scalars['DateTime']>
+  createdAt_gte?: Maybe<Scalars['DateTime']>
+  createdById_eq?: Maybe<Scalars['ID']>
+  createdById_in?: Maybe<Array<Scalars['ID']>>
+  updatedAt_eq?: Maybe<Scalars['DateTime']>
+  updatedAt_lt?: Maybe<Scalars['DateTime']>
+  updatedAt_lte?: Maybe<Scalars['DateTime']>
+  updatedAt_gt?: Maybe<Scalars['DateTime']>
+  updatedAt_gte?: Maybe<Scalars['DateTime']>
+  updatedById_eq?: Maybe<Scalars['ID']>
+  updatedById_in?: Maybe<Array<Scalars['ID']>>
+  deletedAt_all?: Maybe<Scalars['Boolean']>
+  deletedAt_eq?: Maybe<Scalars['DateTime']>
+  deletedAt_lt?: Maybe<Scalars['DateTime']>
+  deletedAt_lte?: Maybe<Scalars['DateTime']>
+  deletedAt_gt?: Maybe<Scalars['DateTime']>
+  deletedAt_gte?: Maybe<Scalars['DateTime']>
+  deletedById_eq?: Maybe<Scalars['ID']>
+  deletedById_in?: Maybe<Array<Scalars['ID']>>
+  transactionalStatus_json?: Maybe<Scalars['JSONObject']>
+  changedAt_eq?: Maybe<Scalars['Int']>
+  changedAt_gt?: Maybe<Scalars['Int']>
+  changedAt_gte?: Maybe<Scalars['Int']>
+  changedAt_lt?: Maybe<Scalars['Int']>
+  changedAt_lte?: Maybe<Scalars['Int']>
+  changedAt_in?: Maybe<Array<Scalars['Int']>>
+  nft?: Maybe<OwnedNftWhereInput>
+  AND?: Maybe<Array<TransactionalStatusUpdateWhereInput>>
+  OR?: Maybe<Array<TransactionalStatusUpdateWhereInput>>
+}
+
+export type TransactionalStatusUpdateWhereUniqueInput = {
+  id: Scalars['ID']
+}
+
 export type UnlockBlogPostProposalDetails = {
   /** The blog post that should be unlocked */
   blogPost: Scalars['String']

+ 1 - 1
tests/integration-tests/src/graphql/queries/content.graphql

@@ -22,7 +22,7 @@ fragment OwnedNftFields on OwnedNft {
     id
   }
   metadata
-  # transactionalStatus TODO
+  transactionalStatus {__typename}
   creatorRoyalty
 }
 

+ 8 - 0
tests/integration-tests/src/scenarios/full.ts

@@ -26,6 +26,9 @@ import runtimeUpgradeProposal from '../flows/proposals/runtimeUpgradeProposal'
 import exactExecutionBlock from '../flows/proposals/exactExecutionBlock'
 import expireProposal from '../flows/proposals/expireProposal'
 import proposalsDiscussion from '../flows/proposalsDiscussion'
+import initStorage, { singleBucketConfig as storageConfig } from '../flows/storage/initStorage'
+import activeVideoCounters from '../flows/content/activeVideoCounters'
+import nftAuctionAndOffers from '../flows/content/nftAuctionAndOffers'
 import { scenario } from '../Scenario'
 
 scenario('Full', async ({ job, env }) => {
@@ -80,4 +83,9 @@ scenario('Full', async ({ job, env }) => {
   // Council
   const secondCouncilJob = job('electing second council', electCouncil).requires(membershipSystemJob)
   job('council election failures', failToElect).requires(secondCouncilJob)
+
+  // Content directory
+  const initStorageJob = job('initialize storage system', initStorage(storageConfig)).requires(sudoHireLead)
+  const videoCountersJob = job('check active video counters', activeVideoCounters).requires(initStorageJob)
+  job('nft auction and offers', nftAuctionAndOffers).after(videoCountersJob)
 })

+ 0 - 1
types/augment/all/defs.json

@@ -642,7 +642,6 @@
         "num_videos": "u64",
         "is_censored": "bool",
         "reward_account": "Option<GenericAccountId>",
-        "deletion_prize_source_account_id": "GenericAccountId",
         "collaborators": "BTreeSet<MemberId>",
         "moderators": "BTreeSet<MemberId>",
         "cumulative_payout_earned": "u128"

+ 0 - 1
types/augment/all/types.ts

@@ -486,7 +486,6 @@ export interface Channel extends Struct {
   readonly num_videos: u64;
   readonly is_censored: bool;
   readonly reward_account: Option<GenericAccountId>;
-  readonly deletion_prize_source_account_id: GenericAccountId;
   readonly collaborators: BTreeSet<MemberId>;
   readonly moderators: BTreeSet<MemberId>;
   readonly cumulative_payout_earned: u128;

+ 0 - 1
types/src/content/index.ts

@@ -121,7 +121,6 @@ export class Channel extends JoyStructDecorated({
   num_videos: u64,
   is_censored: bool,
   reward_account: Option.with(AccountId),
-  deletion_prize_source_account_id: AccountId,
   collaborators: BTreeSet.with(MemberId),
   moderators: BTreeSet.with(MemberId),
   cumulative_payout_earned: Balance,