diff --git a/src/services/orders/aggregations/order.aggregations.ts b/src/services/orders/aggregations/order.aggregations.ts index ab43d1c..d302ed9 100644 --- a/src/services/orders/aggregations/order.aggregations.ts +++ b/src/services/orders/aggregations/order.aggregations.ts @@ -1,4 +1,4 @@ -import { OrderSide, AssetClass } from '../../../models'; +import { OrderSide, AssetClass, OrderStatus } from '../../../models'; import { Utils, TOKENS } from '../../../utils'; import { fetchTokenPrices } from '../../token-prices/token-price.service'; @@ -72,7 +72,10 @@ export const addPriceSortingAggregation = async (orderSide: OrderSide) => { }, { case: { - $eq: ['$make.assetType.contract', Utils.tokenAddresses.weth], + $eq: [ + '$make.assetType.contract', + Utils.tokenAddresses.weth, + ], }, then: { $divide: [ @@ -84,7 +87,10 @@ export const addPriceSortingAggregation = async (orderSide: OrderSide) => { }, { case: { - $eq: ['$make.assetType.contract', Utils.tokenAddresses['usd-coin']], + $eq: [ + '$make.assetType.contract', + Utils.tokenAddresses['usd-coin'], + ], }, then: { $divide: [ @@ -96,7 +102,10 @@ export const addPriceSortingAggregation = async (orderSide: OrderSide) => { }, { case: { - $eq: ['$make.assetType.contract', Utils.tokenAddresses['universe-xyz']], + $eq: [ + '$make.assetType.contract', + Utils.tokenAddresses['universe-xyz'], + ], }, then: { $divide: [ @@ -153,7 +162,10 @@ export const addPriceSortingAggregation = async (orderSide: OrderSide) => { }, { case: { - $eq: ['$take.assetType.contract', Utils.tokenAddresses.weth], + $eq: [ + '$take.assetType.contract', + Utils.tokenAddresses.weth, + ], }, then: { $multiply: [ @@ -169,7 +181,10 @@ export const addPriceSortingAggregation = async (orderSide: OrderSide) => { }, { case: { - $eq: ['$take.assetType.contract', Utils.tokenAddresses['usd-coin']], + $eq: [ + '$take.assetType.contract', + Utils.tokenAddresses['usd-coin'], + ], }, then: { $multiply: [ @@ -185,7 +200,10 @@ export const addPriceSortingAggregation = async (orderSide: OrderSide) => { }, { case: { - $eq: ['$take.assetType.contract', Utils.tokenAddresses['universe-xyz']], + $eq: [ + '$take.assetType.contract', + Utils.tokenAddresses['universe-xyz'], + ], }, then: { $multiply: [ @@ -208,3 +226,34 @@ export const addPriceSortingAggregation = async (orderSide: OrderSide) => { ]; } }; + +export const recentlyListedAggregation = async (timestamp: number) => { + return [ + { + $addFields: { + active: { + $cond: { + if: { + $and: [ + { + $in: [ + '$status', + [OrderStatus.CREATED, OrderStatus.PARTIALFILLED], + ], + }, + { + $or: [{ $lt: ['$start', timestamp] }, { $eq: ['$start', 0] }], + }, + { + $or: [{ $gt: ['$end', timestamp] }, { $eq: ['$end', 0] }], + }, + ], + }, + then: true, + else: false, + }, + }, + }, + }, + ]; +}; diff --git a/src/services/orders/builders/order.builder.ts b/src/services/orders/builders/order.builder.ts index a155ed9..4302086 100644 --- a/src/services/orders/builders/order.builder.ts +++ b/src/services/orders/builders/order.builder.ts @@ -10,6 +10,7 @@ import { import { addEndSortingAggregation, addPriceSortingAggregation, + recentlyListedAggregation, } from '../aggregations/order.aggregations'; import { Utils } from '../../../utils'; @@ -50,9 +51,11 @@ export const buildOrderQueryFilters = async ( side: OrderSide.SELL, }); } - filters.push({ - status: { $in: [OrderStatus.CREATED, OrderStatus.PARTIALFILLED] }, - }); + if (orderSort !== SortOrderOptionsEnum.RecentlyListed) { + filters.push({ + status: { $in: [OrderStatus.CREATED, OrderStatus.PARTIALFILLED] }, + }); + } filters.push({ $or: [{ start: { $lt: utcTimestamp } }, { start: 0 }], }); @@ -196,6 +199,8 @@ export const buildOrderQueryFilters = async ( sort.usd_value = 1; break; case SortOrderOptionsEnum.RecentlyListed: + sortingAggregation = await recentlyListedAggregation(utcTimestamp); + sort.active = -1; sort.createdAt = -1; break; case SortOrderOptionsEnum.TokenIdAscending: @@ -222,5 +227,5 @@ export const buildOrderQueryFilters = async ( console.log('ORDER FILTERS:'); console.log(finalFilters); - return { finalFilters, sortingAggregation, sort }; + return { finalFilters, sortingAggregation, sort, sorting }; }; diff --git a/src/strategies/nft-owner-order.strategy.ts b/src/strategies/nft-owner-order.strategy.ts index 157c5f6..6ac13a5 100644 --- a/src/strategies/nft-owner-order.strategy.ts +++ b/src/strategies/nft-owner-order.strategy.ts @@ -51,7 +51,7 @@ export class NftOwnerOrderStrategy implements IStrategy { ownerParams, nftParams.tokenType.toString(), ); - const { finalFilters, sortingAggregation, sort } = + const { finalFilters, sortingAggregation, sort, sorting } = await buildOrderQueryFilters(orderParams, generalParams); console.time('query-time'); @@ -64,13 +64,16 @@ export class NftOwnerOrderStrategy implements IStrategy { }, }), ownerQuery, - OrderModel.aggregate([{ $match: finalFilters }], { - collation: { - locale: 'en', - strength: 2, - numericOrdering: true, + OrderModel.aggregate( + [{ $match: finalFilters }, ...sortingAggregation, { $sort: sort }], + { + collation: { + locale: 'en', + strength: 2, + numericOrdering: true, + }, }, - }), + ), ]); console.timeEnd('query-time'); @@ -81,6 +84,7 @@ export class NftOwnerOrderStrategy implements IStrategy { } const filtered = []; + const uniqueFiltered = new Set(); for (let i = 0; i < orders.length; i++) { const order = orders[i]; @@ -119,12 +123,15 @@ export class NftOwnerOrderStrategy implements IStrategy { if (!ownersInfo.length) { continue; } - - filtered.push(nft); + if (sorting === 1) { + uniqueFiltered.add(nft.tokenId && nft.contractAddress && nft); + } else { + filtered.push(nft); + } } return { - count: filtered.length, + count: sorting === 1 ? uniqueFiltered.size : filtered.length, }; } @@ -152,7 +159,7 @@ export class NftOwnerOrderStrategy implements IStrategy { ownerParams, nftParams.tokenType.toString(), ); - const { finalFilters, sortingAggregation, sort } = + const { finalFilters, sortingAggregation, sort, sorting } = await buildOrderQueryFilters(orderParams, generalParams); console.time('query-time'); @@ -188,6 +195,7 @@ export class NftOwnerOrderStrategy implements IStrategy { // Apply Pagination const filtered = []; + const uniqueFiltered = new Set(); for (let i = 0; i < orders.length; i++) { const order = orders[i]; @@ -247,26 +255,45 @@ export class NftOwnerOrderStrategy implements IStrategy { nft.orders = nftOrders; nft.owners = ownerAddresses; - filtered.push(nft); - if (filtered.length === generalParams.skippedItems + limit) { - break; + if (sorting === 1) { + uniqueFiltered.add(nft.tokenId && nft.contractAddress && nft); + if (uniqueFiltered.size === generalParams.skippedItems + limit) { + break; + } + } else { + filtered.push(nft); + if (filtered.length === generalParams.skippedItems + limit) { + break; + } } } - if (!filtered.length) { - return { - page: page, - size: limit, - nfts: [], - }; + const emptyResponse = { + page: page, + size: limit, + nfts: [], + }; + + if (sorting === 1) { + if (!uniqueFiltered.size) { + return emptyResponse; + } + } else { + if (!filtered.length) { + return emptyResponse; + } } + const uniqeToArr = [...uniqueFiltered]; + const paginated = filtered.slice(generalParams.skippedItems); + const paginatedUnique = uniqeToArr.slice(generalParams.skippedItems); return { page: page, size: limit, - nfts: paginated, + nfts: sorting === 1 ? paginatedUnique : paginated, + count: paginatedUnique.length, }; } }