diff --git a/schema.graphql b/schema.graphql index 5eb3804f..2de37e53 100644 --- a/schema.graphql +++ b/schema.graphql @@ -298,7 +298,6 @@ type CollectionStats { supply: BigInt tokenCount: Int! salesCount: Int! - rank: Int! marketCap: BigInt! volume: BigInt! } diff --git a/src/createEfiToken.ts b/src/createEfiToken.ts index 78111960..d76d510d 100644 --- a/src/createEfiToken.ts +++ b/src/createEfiToken.ts @@ -26,7 +26,6 @@ export async function createEfiToken(ctx: CommonContext, block: SubstrateBlock) highestSale: null, tokenCount: 1, salesCount: 0, - rank: 0, supply: 2_000_000_000n, marketCap: 0n, volume: 0n, diff --git a/src/mappings/multiTokens/events/attribute_set.ts b/src/mappings/multiTokens/events/attribute_set.ts index 75fddd4f..8323ad0e 100644 --- a/src/mappings/multiTokens/events/attribute_set.ts +++ b/src/mappings/multiTokens/events/attribute_set.ts @@ -63,7 +63,6 @@ export async function attributeSet( highestSale: null, tokenCount: 0, salesCount: 0, - rank: 0, supply: 0n, marketCap: 0n, volume: 0n, diff --git a/src/mappings/multiTokens/events/collection_created.ts b/src/mappings/multiTokens/events/collection_created.ts index 807f3ec2..236bf817 100644 --- a/src/mappings/multiTokens/events/collection_created.ts +++ b/src/mappings/multiTokens/events/collection_created.ts @@ -150,7 +150,6 @@ export async function collectionCreated( highestSale: null, tokenCount: 0, salesCount: 0, - rank: 0, supply: 0n, marketCap: 0n, volume: 0n, diff --git a/src/model/generated/_collectionStats.ts b/src/model/generated/_collectionStats.ts index dbbfa29a..44d852db 100644 --- a/src/model/generated/_collectionStats.ts +++ b/src/model/generated/_collectionStats.ts @@ -8,7 +8,6 @@ export class CollectionStats { private _supply!: bigint | undefined | null private _tokenCount!: number private _salesCount!: number - private _rank!: number private _marketCap!: bigint private _volume!: bigint @@ -21,7 +20,6 @@ export class CollectionStats { this._supply = json.supply == null ? undefined : marshal.bigint.fromJSON(json.supply) this._tokenCount = marshal.int.fromJSON(json.tokenCount) this._salesCount = marshal.int.fromJSON(json.salesCount) - this._rank = marshal.int.fromJSON(json.rank) this._marketCap = marshal.bigint.fromJSON(json.marketCap) this._volume = marshal.bigint.fromJSON(json.volume) } @@ -77,15 +75,6 @@ export class CollectionStats { this._salesCount = value } - get rank(): number { - assert(this._rank != null, 'uninitialized access') - return this._rank - } - - set rank(value: number) { - this._rank = value - } - get marketCap(): bigint { assert(this._marketCap != null, 'uninitialized access') return this._marketCap @@ -112,7 +101,6 @@ export class CollectionStats { supply: this.supply == null ? undefined : marshal.bigint.toJSON(this.supply), tokenCount: this.tokenCount, salesCount: this.salesCount, - rank: this.rank, marketCap: marshal.bigint.toJSON(this.marketCap), volume: marshal.bigint.toJSON(this.volume), } diff --git a/src/services/collection.ts b/src/services/collection.ts index cd881fb2..09f87861 100644 --- a/src/services/collection.ts +++ b/src/services/collection.ts @@ -4,37 +4,6 @@ import { Collection, CollectionStats, Listing, ListingSale, ListingStatus, Token export class CollectionService { constructor(public em: EntityManager) {} - private get salesQuery() { - return this.em - .createQueryBuilder() - .select('l.collection_id AS collection_id') - .addSelect('RANK() OVER (ORDER BY SUM(l.highest_price) DESC NULLS LAST)::int AS rank') - .addSelect('MAX(l.highest_price) AS highest_sale') - .addSelect('MAX(l.last_sale) AS last_sale') - .addSelect('SUM(l.highest_price * l.amount) AS total_volume') - .addSelect('SUM(l.count)::int AS sales') - .from((qb) => { - return qb - .select('listing.id AS id') - .addSelect('COUNT(sale.id) AS count') - .addSelect('listing.highest_price AS highest_price') - .addSelect('collection.id AS collection_id') - .addSelect('listing.amount AS amount') - .addSelect( - 'CASE WHEN lead(listing.id) OVER(PARTITION BY collection.id ORDER BY listing.created_at) IS NULL THEN listing.highest_price END AS last_sale' - ) - .from(Listing, 'listing') - .innerJoin(Token, 'token', 'listing.make_asset_id_id = token.id') - .innerJoin(Collection, 'collection', 'token.collection = collection.id') - .innerJoin(ListingStatus, 'status', `listing.id = status.listing AND status.type = 'Finalized'`) - .leftJoin(ListingSale, 'sale', 'listing.id = sale.listing') - .addGroupBy('listing.id') - .addGroupBy('collection.id') - }, 'l') - .groupBy('l.collection_id') - .getQuery() - } - private floorQuery = `SELECT MIN("listing"."highest_price") AS floor_price FROM "listing" AS "listing" INNER JOIN "token" "token" ON "token"."id" = "listing"."make_asset_id_id" INNER JOIN "collection" "collection" ON "collection"."id" = "token"."collection_id" WHERE "collection"."id" = $1 AND (SELECT count(*) FROM "listing_status" AS "listing_status" WHERE "listing_status"."type" = 'Active' AND "listing_status"."listing_id" = "listing"."id") = (SELECT count(*) FROM "listing_status" AS "listing_status_1" WHERE "listing_status_1"."listing_id" = "listing"."id")` @@ -42,7 +11,32 @@ export class CollectionService { if (!collectionId) throw new Error('null collectionId not allowed') const promises = [ - this.em.query(`;With cte AS (${this.salesQuery}) SELECT * FROM cte WHERE collection_id = $1;`, [collectionId]), + this.em + .createQueryBuilder() + .addSelect('MAX(l.highest_price) AS highest_sale') + .addSelect('MAX(l.last_sale) AS last_sale') + .addSelect('SUM(l.volume) AS total_volume') + .addSelect('SUM(l.count)::int AS sales') + .from((qb) => { + return qb + .select('listing.id AS id') + .addSelect('COUNT(sale.id) AS count') + .addSelect('listing.highest_price AS highest_price') + .addSelect('SUM(sale.amount * sale.price) AS volume') + .addSelect('listing.amount AS amount') + .addSelect( + 'CASE WHEN lead(listing.id) OVER(ORDER BY listing.created_at) IS NULL THEN listing.highest_price END AS last_sale' + ) + .from(ListingSale, 'sale') + .innerJoin(Listing, 'listing', 'listing.id = sale.listing') + .innerJoin(Token, 'token', 'listing.make_asset_id_id = token.id') + .innerJoin(Collection, 'collection', 'token.collection = collection.id') + .leftJoin(ListingStatus, 'status', `listing.id = status.listing AND status.type = 'Finalized'`) + .where('collection.id = :collectionId', { collectionId }) + .groupBy('listing.id') + }, 'l') + .getRawOne(), + this.em.query(this.floorQuery, [collectionId]), this.em .getRepository(Token) @@ -54,13 +48,12 @@ export class CollectionService { ] // eslint-disable-next-line @typescript-eslint/naming-convention - const [[sales], [{ floor_price }], { tokenCount, supply }] = await Promise.all(promises) + const [sales, [{ floor_price }], { tokenCount, supply }] = await Promise.all(promises) const stats = new CollectionStats({ tokenCount: Number(tokenCount), supply: BigInt(supply ?? 0n), salesCount: sales?.sales ?? 0, - rank: sales?.rank ?? 0, volume: sales?.total_volume ?? 0n, marketCap: BigInt(sales?.last_sale ?? 0n) * BigInt(tokenCount), floorPrice: floor_price,