Skip to content

Commit eef4e03

Browse files
authored
Merge pull request #1048 from multiversx/SERVICES-1887-add-remove-whitelist-collection
Add remove whitelist collection
2 parents 606bf50 + fa4e938 commit eef4e03

9 files changed

+170
-15
lines changed

schema.gql

+6
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,7 @@ type Mutation {
995995
removeBlacklistedCollection(collection: String!): Boolean!
996996
removeFeaturedCollection(input: FeaturedCollectionsArgs!): Boolean!
997997
removeLike(input: RemoveLikeArgs!): Boolean!
998+
removeWhitelistCollection(input: RemoveWhitelistCollectionArgs!): Boolean!
998999
reportCollection(
9991000
"""This endpoint can be used to report a Collection"""
10001001
input: ReportCollectionInput!
@@ -1341,6 +1342,11 @@ input RemoveLikeArgs {
13411342
identifier: String!
13421343
}
13431344

1345+
input RemoveWhitelistCollectionArgs {
1346+
collection: String!
1347+
marketplaceKey: String!
1348+
}
1349+
13441350
input ReportCollectionInput {
13451351
collectionIdentifier: String!
13461352
}

src/common/persistence/persistence.service.ts

+13-5
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,13 @@ export class PersistenceService {
259259
this.marketplaceCollectionsRepository.getMarketplaceByKeyAndCollection(collection, key),
260260
);
261261
}
262+
263+
async getCollectionByKeyAndCollection(collection: string, key: string): Promise<MarketplaceCollectionEntity> {
264+
return await this.execute(
265+
this.getCollectionByKeyAndCollection.name,
266+
this.marketplaceCollectionsRepository.getCollectionByKeyAndCollection(collection, key),
267+
);
268+
}
262269
async getAllMarketplaceCollections(): Promise<MarketplaceCollectionEntity[]> {
263270
return await this.execute(this.getAllMarketplaceCollections.name, this.marketplaceCollectionsRepository.getAllCollections());
264271
}
@@ -277,11 +284,12 @@ export class PersistenceService {
277284
);
278285
}
279286

280-
async saveMarketplaceCollection(entity: MarketplaceCollectionEntity): Promise<MarketplaceCollectionEntity> {
281-
return await this.execute(
282-
this.getCollectionsByMarketplace.name,
283-
this.marketplaceCollectionsRepository.saveMarketplaceCollection(entity),
284-
);
287+
async saveMarketplaceCollection(entity: MarketplaceCollectionEntity): Promise<boolean> {
288+
return await this.execute(this.saveMarketplaceCollection.name, this.marketplaceCollectionsRepository.saveMarketplaceCollection(entity));
289+
}
290+
291+
async deleteMarketplaceCollection(entity: MarketplaceCollectionEntity): Promise<MarketplaceCollectionEntity> {
292+
return this.execute(this.deleteMarketplaceCollection.name, this.marketplaceCollectionsRepository.deleteMarketplaceCollection(entity));
285293
}
286294

287295
async saveMarketplace(entity: MarketplaceEntity): Promise<MarketplaceEntity> {

src/db/marketplaces/marketplace-collections.repository.ts

+23-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Injectable } from '@nestjs/common';
22
import { InjectRepository } from '@nestjs/typeorm';
3-
import { Repository } from 'typeorm';
3+
import { DeleteResult, Repository } from 'typeorm';
44
import { MarketplaceCollectionEntity } from './marketplace-collection.entity';
55
import { MarketplaceEntity } from './marketplace.entity';
66

@@ -87,7 +87,27 @@ export class MarketplaceCollectionsRepository {
8787
.execute();
8888
}
8989

90-
async saveMarketplaceCollection(entity: MarketplaceCollectionEntity): Promise<MarketplaceCollectionEntity> {
91-
return await this.marketplaceCollectionRepository.save(entity);
90+
async getCollectionByIdentifier(collectionIdentifier: string): Promise<MarketplaceCollectionEntity> {
91+
return this.marketplaceCollectionRepository.findOne({
92+
where: [{ collectionIdentifier: collectionIdentifier }],
93+
});
94+
}
95+
96+
async getCollectionByKeyAndCollection(collection: string, key: string): Promise<MarketplaceCollectionEntity> {
97+
return this.marketplaceCollectionRepository
98+
.createQueryBuilder('mc')
99+
.select('mc.*')
100+
.leftJoin('mc.marketplaces', 'm')
101+
.where(`collectionIdentifier = '${collection}' and m.key= '${key}'`)
102+
.execute();
103+
}
104+
105+
async saveMarketplaceCollection(entity: MarketplaceCollectionEntity): Promise<boolean> {
106+
const result = await this.marketplaceCollectionRepository.save(entity);
107+
return result ? true : false;
108+
}
109+
110+
async deleteMarketplaceCollection(entity: MarketplaceCollectionEntity): Promise<MarketplaceCollectionEntity> {
111+
return await this.marketplaceCollectionRepository.remove(entity);
92112
}
93113
}

src/modules/analytics/collections-analytics.service.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ export class CollectionsAnalyticsService {
8080
return await this.analyticsGetter.getVolumeDataForTimePeriod(time, series, metric);
8181
}
8282

83-
public async getFloorPriceVolumeForTimePeriod(time: string, series: string, metric: string): Promise<AnalyticsAggregateValue[]> {
83+
public async getFloorPriceVolumeForTimePeriod(
84+
time: string,
85+
series: string,
86+
metric: string = 'floorPriceUSD',
87+
): Promise<AnalyticsAggregateValue[]> {
8488
return await this.analyticsGetter.getFloorPriceForTimePeriod(time, series, metric);
8589
}
8690

src/modules/marketplaces/marketplaces-mutations.resolver.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { Resolver, Args, Mutation } from '@nestjs/graphql';
22
import { BaseResolver } from '../common/base.resolver';
33
import { Marketplace } from './models';
44
import { MarketplacesService } from './marketplaces.service';
5-
import { WhitelistCollectionArgs } from './models/WhitelistCollectionArgs';
6-
import { WhitelistCollectionRequest } from './models/requests/WhitelistCollectionOnMarketplaceRequest';
5+
import { RemoveWhitelistCollectionArgs, WhitelistCollectionArgs } from './models/WhitelistCollectionArgs';
6+
import { RemoveWhitelistCollectionRequest, WhitelistCollectionRequest } from './models/requests/WhitelistCollectionOnMarketplaceRequest';
77
import { WhitelistMarketplaceArgs } from './models/WhitelistMarketplaceArgs';
88
import { WhitelistMarketplaceRequest } from './models/requests/WhitelistMarketplaceRequest';
99
import { UseGuards } from '@nestjs/common';
@@ -24,6 +24,12 @@ export class MarketplacesMutationsResolver extends BaseResolver(Marketplace) {
2424
return this.marketplaceService.whitelistCollectionOnMarketplace(WhitelistCollectionRequest.fromArgs(input));
2525
}
2626

27+
@Mutation(() => Boolean)
28+
@UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard)
29+
async removeWhitelistCollection(@Args('input') input: RemoveWhitelistCollectionArgs): Promise<Boolean> {
30+
return this.marketplaceService.removeWhitelistCollection(RemoveWhitelistCollectionRequest.fromArgs(input));
31+
}
32+
2733
@Mutation(() => Boolean)
2834
@UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard)
2935
async updateMarketplace(@Args('input') input: UpdateMarketplaceArgs): Promise<Boolean> {

src/modules/marketplaces/marketplaces.service.ts

+27-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { MarketplaceCollectionEntity, MarketplaceEntity } from 'src/db/marketpla
77
import { MarketplaceTypeEnum } from './models/MarketplaceType.enum';
88
import { MarketplaceFilters } from './models/Marketplace.Filter';
99
import { PersistenceService } from 'src/common/persistence/persistence.service';
10-
import { WhitelistCollectionRequest } from './models/requests/WhitelistCollectionOnMarketplaceRequest';
10+
import { RemoveWhitelistCollectionRequest, WhitelistCollectionRequest } from './models/requests/WhitelistCollectionOnMarketplaceRequest';
1111
import { BadRequestError } from 'src/common/models/errors/bad-request-error';
1212
import { WhitelistMarketplaceRequest } from './models/requests/WhitelistMarketplaceRequest';
1313
import { UpdateMarketplaceRequest } from './models/requests/UpdateMarketplaceRequest';
@@ -180,7 +180,7 @@ export class MarketplacesService {
180180
if (savedCollection) {
181181
this.triggerCacheInvalidation(request.marketplaceKey, request.collection, marketplace.address);
182182
}
183-
return savedCollection ? true : false;
183+
return savedCollection;
184184
} catch (error) {
185185
this.logger.error('An error has occured while whitelisting collection', {
186186
path: this.whitelistCollectionOnMarketplace.name,
@@ -192,6 +192,31 @@ export class MarketplacesService {
192192
}
193193
}
194194

195+
async removeWhitelistCollection(request: RemoveWhitelistCollectionRequest): Promise<Boolean> {
196+
const collection = await this.persistenceService.getCollectionByKeyAndCollection(request.collection, request.marketplaceKey);
197+
const marketplace = await this.persistenceService.getMarketplaceByKey(request.marketplaceKey);
198+
199+
if (!collection || !marketplace) {
200+
throw new BadRequestError('Marketplace not available for this key, choose another key if this is not your marketplace');
201+
}
202+
try {
203+
const removedCollection = await this.persistenceService.deleteMarketplaceCollection(collection);
204+
205+
if (removedCollection) {
206+
this.triggerCacheInvalidation(request.marketplaceKey, request.collection, marketplace.address);
207+
}
208+
return removedCollection ? true : false;
209+
} catch (error) {
210+
this.logger.error('An error has occured while remove whitelist for collection', {
211+
path: this.whitelistCollectionOnMarketplace.name,
212+
collection: request?.collection,
213+
marketplace: request?.marketplaceKey,
214+
exception: error,
215+
});
216+
return false;
217+
}
218+
}
219+
195220
async whitelistMarketplace(request: WhitelistMarketplaceRequest): Promise<Boolean> {
196221
const marketplace = await this.persistenceService.getMarketplaceByKey(request.marketplaceKey);
197222
if (marketplace) {

src/modules/marketplaces/models/WhitelistCollectionArgs.ts

+13
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,16 @@ export class WhitelistCollectionArgs {
1414
@Field()
1515
marketplaceKey: string;
1616
}
17+
18+
@InputType()
19+
export class RemoveWhitelistCollectionArgs {
20+
@Matches(RegExp(COLLECTION_IDENTIFIER_RGX), {
21+
message: COLLECTION_IDENTIFIER_ERROR,
22+
})
23+
@Field()
24+
collection: string;
25+
26+
@MaxLength(62)
27+
@Field()
28+
marketplaceKey: string;
29+
}

src/modules/marketplaces/models/requests/WhitelistCollectionOnMarketplaceRequest.ts

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { WhitelistCollectionArgs } from '../WhitelistCollectionArgs';
1+
import { RemoveWhitelistCollectionArgs, WhitelistCollectionArgs } from '../WhitelistCollectionArgs';
22

33
export class WhitelistCollectionRequest {
44
collection: string;
@@ -14,3 +14,18 @@ export class WhitelistCollectionRequest {
1414
});
1515
}
1616
}
17+
18+
export class RemoveWhitelistCollectionRequest {
19+
collection: string;
20+
marketplaceKey: string;
21+
constructor(init?: Partial<RemoveWhitelistCollectionRequest>) {
22+
Object.assign(this, init);
23+
}
24+
25+
static fromArgs(args: RemoveWhitelistCollectionArgs) {
26+
return new RemoveWhitelistCollectionRequest({
27+
collection: args.collection,
28+
marketplaceKey: args.marketplaceKey,
29+
});
30+
}
31+
}

src/modules/marketplaces/tests/marketplaces.service.spec.ts

+59-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { MarketplaceCollectionEntity, MarketplaceEntity } from 'src/db/marketpla
77
import { MarketplaceTypeEnum } from '../models/MarketplaceType.enum';
88
import { MarketplaceFilters } from '../models/Marketplace.Filter';
99
import { Marketplace } from '../models';
10-
import { WhitelistCollectionRequest } from '../models/requests/WhitelistCollectionOnMarketplaceRequest';
10+
import { RemoveWhitelistCollectionRequest, WhitelistCollectionRequest } from '../models/requests/WhitelistCollectionOnMarketplaceRequest';
1111
import { BadRequestError } from 'src/common/models/errors/bad-request-error';
1212
import { Logger } from '@nestjs/common';
1313
import { WhitelistMarketplaceRequest } from '../models/requests/WhitelistMarketplaceRequest';
@@ -738,6 +738,64 @@ describe('Marketplaces Service', () => {
738738
});
739739
});
740740

741+
describe('removeWhitelistCollection', () => {
742+
it('when marketplace not found throws error', async () => {
743+
const persistenceService = module.get<PersistenceService>(PersistenceService);
744+
745+
persistenceService.getMarketplaceByKey = jest.fn().mockReturnValueOnce(null);
746+
persistenceService.getCollectionByKeyAndCollection = jest.fn().mockReturnValueOnce(new MarketplaceCollectionEntity());
747+
748+
await expect(service.removeWhitelistCollection(new RemoveWhitelistCollectionRequest())).rejects.toThrowError(BadRequestError);
749+
});
750+
751+
it('when collection not found throws error', async () => {
752+
const persistenceService = module.get<PersistenceService>(PersistenceService);
753+
754+
persistenceService.getMarketplaceByKey = jest.fn().mockReturnValueOnce(inputMarketplace[0]);
755+
persistenceService.getCollectionByKeyAndCollection = jest.fn().mockReturnValueOnce(null);
756+
757+
await expect(service.removeWhitelistCollection(new RemoveWhitelistCollectionRequest())).rejects.toThrowError(BadRequestError);
758+
});
759+
760+
it('when marketplace exists and delete fails returns false', async () => {
761+
const persistenceService = module.get<PersistenceService>(PersistenceService);
762+
763+
persistenceService.getMarketplaceByKey = jest.fn().mockReturnValueOnce(inputMarketplace[0]);
764+
persistenceService.getCollectionByKeyAndCollection = jest.fn().mockReturnValueOnce(new MarketplaceCollectionEntity());
765+
766+
persistenceService.deleteMarketplaceCollection = jest.fn(() => {
767+
throw new Error();
768+
});
769+
770+
const expectedResult = await service.removeWhitelistCollection(
771+
new RemoveWhitelistCollectionRequest({ marketplaceKey: 'xoxno', collection: 'identifier' }),
772+
);
773+
774+
expect(expectedResult).toBeFalsy();
775+
});
776+
777+
it('when marketplace exists and save is succesfull returns true', async () => {
778+
const persistenceService = module.get<PersistenceService>(PersistenceService);
779+
const eventPublisher = module.get<CacheEventsPublisherService>(CacheEventsPublisherService);
780+
781+
eventPublisher.publish = jest.fn();
782+
persistenceService.getMarketplaceByKey = jest.fn().mockReturnValueOnce(inputMarketplace[0]);
783+
persistenceService.getCollectionByKeyAndCollection = jest.fn().mockReturnValueOnce(new MarketplaceCollectionEntity());
784+
785+
persistenceService.deleteMarketplaceCollection = jest.fn().mockReturnValueOnce(
786+
new MarketplaceCollectionEntity({
787+
collectionIdentifier: 'collection',
788+
marketplaces: [inputMarketplace[0]],
789+
}),
790+
);
791+
const expectedResult = await service.removeWhitelistCollection(
792+
new RemoveWhitelistCollectionRequest({ marketplaceKey: 'xoxno', collection: 'identifier' }),
793+
);
794+
795+
expect(expectedResult).toBeTruthy();
796+
});
797+
});
798+
741799
describe('whitelistMarketplace', () => {
742800
it('when marketplace key exists throws error', async () => {
743801
const persistenceService = module.get<PersistenceService>(PersistenceService);

0 commit comments

Comments
 (0)