Pārlūkot izejas kodu

Query for ending london auctions nfts (#115)

* endingAuctionsNfts query

* lint

* CR fixes: removed archive, modified query, minor fixes

* returned completion check

---------

Co-authored-by: Artem <Artem Slugin>
Co-authored-by: Leszek Wiesner <leszek@jsgenesis.com>
attemka 1 gadu atpakaļ
vecāks
revīzija
52e66ba2e1

+ 70 - 4
src/server-extension/resolvers/NftResolver/index.ts

@@ -1,15 +1,81 @@
-import { Args, Ctx, Mutation, Resolver } from 'type-graphql'
+import { Args, Ctx, Info, Mutation, Query, Resolver } from 'type-graphql'
 import { EntityManager } from 'typeorm'
-import { RequestFeaturedNftArgs, NftFeaturedRequstInfo } from './types'
+import { RequestFeaturedNftArgs, NftFeaturedRequstInfo, EndingAuctionsNftsArgs } from './types'
 import { ContextWithIP } from '../../check'
-import { withHiddenEntities } from '../../../utils/sql'
-import { NftFeaturingRequest, OwnedNft } from '../../../model'
+import { extendClause, withHiddenEntities } from '../../../utils/sql'
+import { NftFeaturingRequest } from '../../../model'
+import { OwnedNft } from '../baseTypes'
 import { randomAsHex } from '@polkadot/util-crypto'
+import { GraphQLResolveInfo } from 'graphql'
+import { Context } from '@subsquid/openreader/lib/context'
+import { model } from '../model'
+import { parseAnyTree, parseSqlArguments } from '@subsquid/openreader/lib/opencrud/tree'
+import { getResolveTree } from '@subsquid/openreader/lib/util/resolve-tree'
+import { ListQuery } from '@subsquid/openreader/lib/sql/query'
+import { isObject } from 'lodash'
+import { has } from '../../../utils/misc'
 
 @Resolver()
 export class NftResolver {
   constructor(private em: () => Promise<EntityManager>) {}
 
+  @Query(() => [OwnedNft])
+  async endingAuctionsNfts(
+    @Args() args: EndingAuctionsNftsArgs,
+    @Info() info: GraphQLResolveInfo,
+    @Ctx() ctx: Context
+  ): Promise<OwnedNft[]> {
+    const em = await this.em()
+    const dbResult: unknown = await em.query('SELECT "height" FROM "squid_processor"."status"')
+    const lastProcessedBlock =
+      Array.isArray(dbResult) &&
+      isObject(dbResult[0]) &&
+      has(dbResult[0], 'height') &&
+      typeof dbResult[0].height === 'number'
+        ? dbResult[0].height
+        : -1
+
+    const tree = getResolveTree(info)
+
+    const sqlArgs = parseSqlArguments(model, 'OwnedNft', {
+      ...args,
+    })
+
+    // Extract subsquid-supported OwnedNft fields
+    const ownedNftFields = parseAnyTree(model, 'OwnedNft', info.schema, tree)
+
+    // Generate query using subsquid's ListQuery
+    const listQuery = new ListQuery(
+      model,
+      ctx.openreader.dialect,
+      'OwnedNft',
+      ownedNftFields,
+      sqlArgs
+    )
+    let listQuerySql = listQuery.sql
+
+    listQuerySql = extendClause(
+      listQuerySql,
+      'FROM',
+      `
+        INNER JOIN (
+          SELECT nft_id, auction_type->>'plannedEndAtBlock' AS end_block FROM auction a
+          WHERE auction_type->>'isTypeOf' = 'AuctionTypeEnglish'
+          AND (auction_type->>'plannedEndAtBlock')::int > ${lastProcessedBlock}
+          AND a.is_canceled = false
+          AND a.is_completed = false
+        ) AS auctions ON auctions.nft_id = owned_nft.id 
+`,
+      ''
+    )
+    listQuerySql = extendClause(listQuerySql, 'ORDER BY', 'end_block::int asc', '')
+    ;(listQuery as { sql: string }).sql = listQuerySql
+
+    const result = await ctx.openreader.executeQuery(listQuery)
+
+    return result
+  }
+
   @Mutation(() => NftFeaturedRequstInfo)
   async requestNftFeatured(
     @Args() { nftId, rationale }: RequestFeaturedNftArgs,

+ 14 - 1
src/server-extension/resolvers/NftResolver/types.ts

@@ -1,6 +1,19 @@
-import { ArgsType, Field, ObjectType } from 'type-graphql'
+import { ArgsType, Field, Int, ObjectType } from 'type-graphql'
 import { MaxLength } from 'class-validator'
 import { DateTime } from '@subsquid/graphql-server'
+import { OwnedNftWhereInput } from '../baseTypes'
+
+@ArgsType()
+export class EndingAuctionsNftsArgs {
+  @Field(() => OwnedNftWhereInput, { nullable: true })
+  where?: Record<string, unknown>
+
+  @Field(() => Int, { nullable: true })
+  limit?: number
+
+  @Field(() => Int, { nullable: true })
+  offset?: number
+}
 
 @ArgsType()
 export class RequestFeaturedNftArgs {

+ 8 - 0
src/server-extension/resolvers/baseTypes.ts

@@ -9,6 +9,11 @@ export class Channel {
   @Field(() => String, { nullable: false }) id!: string
 }
 
+@ObjectType()
+export class OwnedNft {
+  @Field(() => String, { nullable: false }) id!: string
+}
+
 export const ChannelWhereInput = new GraphQLScalarType({
   name: 'ChannelWhereInput',
 })
@@ -51,3 +56,6 @@ registerEnumType(VideoOrderByInput, { name: 'VideoOrderByInput' })
 export class VideosConnection {
   @Field(() => Int, { nullable: false }) totalCount!: number
 }
+export const OwnedNftWhereInput = new GraphQLScalarType({
+  name: 'OwnedNftWhereInput',
+})

+ 18 - 0
src/tests/v2/generated/queries.ts

@@ -591,6 +591,16 @@ export type GetNftsConnectionQuery = {
   }
 }
 
+export type GetEndingAuctionsNftsQueryVariables = Types.Exact<{
+  where?: Types.Maybe<Types.OwnedNftWhereInput>
+  limit?: Types.Maybe<Types.Scalars['Int']>
+  offset?: Types.Maybe<Types.Scalars['Int']>
+}>
+
+export type GetEndingAuctionsNftsQuery = {
+  endingAuctionsNfts: Array<Types.Maybe<FullNftFieldsFragment>>
+}
+
 export type GetNotificationsQueryVariables = Types.Exact<{
   memberId: Types.Scalars['String']
   limit: Types.Scalars['Int']
@@ -2974,6 +2984,14 @@ export const GetNftsConnection = gql`
   }
   ${FullNftFields}
 `
+export const GetEndingAuctionsNfts = gql`
+  query GetEndingAuctionsNfts($where: OwnedNftWhereInput, $limit: Int, $offset: Int) {
+    endingAuctionsNfts(where: $where, limit: $limit, offset: $offset) {
+      ...FullNftFields
+    }
+  }
+  ${FullNftFields}
+`
 export const GetNotifications = gql`
   query GetNotifications($memberId: String!, $limit: Int!) {
     notifications(

+ 7 - 0
src/tests/v2/generated/schema.ts

@@ -4279,6 +4279,7 @@ export type Query = {
   distributionBucketOperatorsConnection: DistributionBucketOperatorsConnection
   distributionBuckets: Array<DistributionBucket>
   distributionBucketsConnection: DistributionBucketsConnection
+  endingAuctionsNfts: Array<Maybe<OwnedNft>>
   eventById?: Maybe<Event>
   /** @deprecated Use eventById */
   eventByUniqueInput?: Maybe<Event>
@@ -4789,6 +4790,12 @@ export type QueryDistributionBucketsConnectionArgs = {
   where?: Maybe<DistributionBucketWhereInput>
 }
 
+export type QueryEndingAuctionsNftsArgs = {
+  limit?: Maybe<Scalars['Int']>
+  offset?: Maybe<Scalars['Int']>
+  where?: Maybe<OwnedNftWhereInput>
+}
+
 export type QueryEventByIdArgs = {
   id: Scalars['String']
 }

+ 6 - 0
src/tests/v2/queries/atlasQueries/nfts.graphql

@@ -38,3 +38,9 @@ query GetNftsConnection(
     totalCount
   }
 }
+
+query GetEndingAuctionsNfts($where: OwnedNftWhereInput, $limit: Int, $offset: Int) {
+  endingAuctionsNfts(where: $where, limit: $limit, offset: $offset) {
+    ...FullNftFields
+  }
+}

+ 5 - 0
src/tests/v2/schema.graphql

@@ -1002,6 +1002,11 @@ type Query {
     first: Int
     where: NftActivityWhereInput
   ): NftActivitiesConnection!
+  endingAuctionsNfts(
+    where: OwnedNftWhereInput
+    offset: Int
+    limit: Int
+  ): [OwnedNft]!
   memberMetadata(
     where: MemberMetadataWhereInput
     orderBy: [MemberMetadataOrderByInput!]