diff --git a/db/migrations/1711017751137-Data.js b/db/migrations/1711017751137-Data.js new file mode 100644 index 00000000..705325f4 --- /dev/null +++ b/db/migrations/1711017751137-Data.js @@ -0,0 +1,11 @@ +module.exports = class Data1711017751137 { + name = 'Data1711017751137' + + async up(db) { + await db.query(`ALTER TABLE "token_entity" ADD "deleted" boolean NOT NULL`) + } + + async down(db) { + await db.query(`ALTER TABLE "token_entity" DROP COLUMN "deleted"`) + } +} diff --git a/schema.graphql b/schema.graphql index 1f209f81..82c5b61c 100644 --- a/schema.graphql +++ b/schema.graphql @@ -51,6 +51,7 @@ type TokenEntity @entity { createdAt: DateTime! supply: Int! count: Int! + deleted: Boolean! } # Entity to represent a collection diff --git a/src/mappings/shared/token/tokenAPI.ts b/src/mappings/shared/token/tokenAPI.ts index e8b9f706..8895a0b8 100644 --- a/src/mappings/shared/token/tokenAPI.ts +++ b/src/mappings/shared/token/tokenAPI.ts @@ -20,7 +20,7 @@ export class TokenAPI { collection, name: tokenName(nft.name, collection.id), count: 1, - supply: 1, + supply: nft.burned ? 0 : 1, hash: md5(tokenId), image: nft.image, media: nft.media, @@ -29,6 +29,7 @@ export class TokenAPI { blockNumber: nft.blockNumber, updatedAt: nft.updatedAt, id: tokenId, + deleted: false, }) await this.store.save(token) @@ -46,11 +47,18 @@ export class TokenAPI { await emOf(this.store).update(NE, nft.id, { token: null }) const updatedCount = await emOf(this.store).countBy(NE, { token: { - id: token.id, + id: token.id, }, - }) + }) + + const updatedSupply = await emOf(this.store).countBy(NE, { + token: { + id: token.id, + }, + burned: false, + }) await emOf(this.store).update(TE, token.id, { - supply: token.supply - 1, + supply: updatedSupply, count: updatedCount, updatedAt: nft.updatedAt, }) @@ -58,7 +66,7 @@ export class TokenAPI { if (updatedCount === 0) { debug(OPERATION, { deleteEmptyToken: `delete empty token ${token.id}` }) try { - await emOf(this.store).delete(TE, token.id) + await emOf(this.store).update(TE, token.id, { deleted: true }) } catch (error) { debug(OPERATION, { deleteEmptyToken: `Failed to delete token ${token.id}`, @@ -69,10 +77,14 @@ export class TokenAPI { } async addNftToToken(nft: NE, token: TE): Promise { + if (nft.token?.id === token.id) { + return token + } debug(OPERATION, { updateToken: `Add NFT ${nft.id} to TOKEN ${token.id} for ` }) token.count += 1 - token.supply += 1 + token.supply += nft.burned ? 0 : 1 token.updatedAt = nft.updatedAt + token.deleted = false nft.token = token await this.store.save(token) await this.store.save(nft) diff --git a/src/model/generated/tokenEntity.model.ts b/src/model/generated/tokenEntity.model.ts index 46c5d57d..acf0c4c1 100644 --- a/src/model/generated/tokenEntity.model.ts +++ b/src/model/generated/tokenEntity.model.ts @@ -55,4 +55,7 @@ export class TokenEntity { @Column_("int4", {nullable: false}) count!: number + + @Column_("bool", {nullable: false}) + deleted!: boolean } diff --git a/src/server-extension/query/tokenEntities.ts b/src/server-extension/query/tokenEntities.ts index 4b27a787..b74c97f8 100644 --- a/src/server-extension/query/tokenEntities.ts +++ b/src/server-extension/query/tokenEntities.ts @@ -62,5 +62,6 @@ FROM LEFT JOIN cheapest ON t.id = cheapest.token_id WHERE nc.supply > 0 AND + t.deleted = false AND ($10::text IS NULL OR LOWER(t.name) LIKE LOWER('%' || $10 || '%')) ` diff --git a/src/server-extension/query/totalTokenEntities.ts b/src/server-extension/query/totalTokenEntities.ts index c936c2cb..6559534e 100644 --- a/src/server-extension/query/totalTokenEntities.ts +++ b/src/server-extension/query/totalTokenEntities.ts @@ -1,13 +1,15 @@ export const totalTokenEntities = ` -SELECT COUNT(DISTINCT token_id) as total_count -FROM nft_entity +SELECT COUNT(DISTINCT ne.token_id) as total_count +FROM nft_entity as ne +JOIN token_entity ON ne.token_id = token_entity.id AND +token_entity.deleted = false WHERE - ($1::text IS NULL OR current_owner = $1) AND - ($6::text IS NULL OR issuer = $6) AND - ($5::text[] IS NULL OR issuer NOT IN (SELECT unnest($5))) AND - ($2::bigint IS NULL OR price >= $2::bigint) AND - ($3::bigint IS NULL OR price > $3::bigint) AND - ($4::bigint IS NULL OR price <= $4::bigint) AND - ($7::text[] IS NULL OR nft_entity.collection_id = ANY($7)) AND - ($8::text IS NULL OR LOWER(nft_entity.name) LIKE LOWER('%' || $8 || '%')); -` + ($1::text IS NULL OR ne.current_owner = $1) AND + ($6::text IS NULL OR ne.issuer = $6) AND + ($5::text[] IS NULL OR ne.issuer NOT IN (SELECT unnest($5))) AND + ($2::bigint IS NULL OR ne.price >= $2::bigint) AND + ($3::bigint IS NULL OR ne.price > $3::bigint) AND + ($4::bigint IS NULL OR ne.price <= $4::bigint) AND + ($7::text[] IS NULL OR ne.collection_id = ANY($7)) AND + ($8::text IS NULL OR LOWER(ne.name) LIKE LOWER('%' || $8 || '%')); +`;