From 14f47d9b14effcf7ec6c18960aaf3626fb34b4f8 Mon Sep 17 00:00:00 2001 From: Juanma Hidalgo Date: Wed, 8 Nov 2023 13:39:28 +0100 Subject: [PATCH] feat: introduce logic to fetch catalog from the marketplace-server (#1967) * feat: introduce logic to fetch catalog from the marketplace-server * feat: use correct URL for the marketplace server * feat: wait for FFs to be loaded * fix: card overflow is clickeable * test: fix broken tests * feat: add generator getCatalogAPI to abstract the API selection logic * chore: remove unwanted comment * fix: wait for identity success action before fetching catalog (#1974) * feat: remove old import * test: fix broken test * chore: reset dev.json values --- webapp/src/components/AssetCard/AssetCard.css | 1 + webapp/src/modules/favorites/sagas.spec.ts | 123 +++++++++++++----- webapp/src/modules/favorites/sagas.ts | 24 +++- webapp/src/modules/features/selectors.ts | 10 ++ webapp/src/modules/features/types.ts | 5 +- webapp/src/modules/features/utils.spec.ts | 32 +++++ webapp/src/modules/features/utils.ts | 16 +++ webapp/src/modules/item/sagas.spec.ts | 58 +++++++-- webapp/src/modules/item/sagas.ts | 24 +++- webapp/src/modules/routing/search.ts | 2 +- .../modules/vendor/decentraland/nft/api.ts | 6 +- 11 files changed, 245 insertions(+), 56 deletions(-) create mode 100644 webapp/src/modules/features/utils.spec.ts create mode 100644 webapp/src/modules/features/utils.ts diff --git a/webapp/src/components/AssetCard/AssetCard.css b/webapp/src/components/AssetCard/AssetCard.css index aac720f9c5..1c748b2a2e 100644 --- a/webapp/src/components/AssetCard/AssetCard.css +++ b/webapp/src/components/AssetCard/AssetCard.css @@ -4,6 +4,7 @@ } .ui.card.AssetCard.catalog { + overflow: hidden; height: 360px; } diff --git a/webapp/src/modules/favorites/sagas.spec.ts b/webapp/src/modules/favorites/sagas.spec.ts index 4dec4c02d9..a306a2ff54 100644 --- a/webapp/src/modules/favorites/sagas.spec.ts +++ b/webapp/src/modules/favorites/sagas.spec.ts @@ -22,6 +22,7 @@ import { import { locations } from '../routing/locations' import { SortDirection } from '../routing/types' import { CatalogAPI } from '../vendor/decentraland/catalog/api' +import { getIsMarketplaceServerEnabled } from '../features/selectors' import { getData as getItemsData } from '../item/selectors' import { BULK_PICK_SUCCESS, @@ -100,7 +101,8 @@ describe('when handling the request for fetching favorited items', () => { return expectSaga(favoritesSaga, getIdentity) .provide([ [select(getListId), listId], - [select(getAddress), Promise.reject(error)] + [select(getAddress), Promise.reject(error)], + [select(getIsMarketplaceServerEnabled), true] ]) .put(fetchFavoritedItemsFailure(error.message)) .dispatch(fetchFavoritedItemsRequest(options)) @@ -114,6 +116,7 @@ describe('when handling the request for fetching favorited items', () => { .provide([ [select(getListId), listId], [select(getAddress), address], + [select(getIsMarketplaceServerEnabled), true], [call(getAccountIdentity), Promise.reject(error)] ]) .put(fetchFavoritedItemsFailure(error.message)) @@ -129,6 +132,7 @@ describe('when handling the request for fetching favorited items', () => { .provide([ [select(getListId), listId], [select(getAddress), address], + [select(getIsMarketplaceServerEnabled), true], [call(getAccountIdentity), Promise.resolve()], [ matchers.call.fn(FavoritesAPI.prototype.getPicksByList), @@ -149,6 +153,7 @@ describe('when handling the request for fetching favorited items', () => { let favoritedItemIds: FavoritedItems let createdAt: Record let total: number + let isMarketplaceFFOn: boolean describe("and there's more than one favorited item", () => { beforeEach(() => { @@ -157,35 +162,79 @@ describe('when handling the request for fetching favorited items', () => { total = 1 }) - describe('and the call to the items api fails', () => { - it('should dispatch an action signaling the failure of the handled action', () => { - return expectSaga(favoritesSaga, getIdentity) - .provide([ - [select(getListId), listId], - [select(getAddress), address], - [call(getAccountIdentity), Promise.resolve()], - [ - matchers.call.fn(FavoritesAPI.prototype.getPicksByList), - Promise.resolve({ results: favoritedItemIds, total }) - ], - [ - matchers.call.fn(CatalogAPI.prototype.get), - Promise.reject(error) - ] - ]) - .call.like({ - fn: CatalogAPI.prototype.get, - args: [ - { - ...options.filters, - first: 1, - ids: [favoritedItemIds[0].itemId] - } - ] - }) - .put(fetchFavoritedItemsFailure(error.message)) - .dispatch(fetchFavoritedItemsRequest(options)) - .run({ silenceTimeout: true }) + describe('and the marketplace-server flag is off', () => { + beforeEach(() => { + isMarketplaceFFOn = false + }) + describe('and the call to the items api fails', () => { + it('should dispatch an action signaling the failure of the handled action', () => { + return expectSaga(favoritesSaga, getIdentity) + .provide([ + [select(getListId), listId], + [select(getIsMarketplaceServerEnabled), isMarketplaceFFOn], + [select(getAddress), address], + [call(getAccountIdentity), Promise.resolve()], + [ + matchers.call.fn(FavoritesAPI.prototype.getPicksByList), + Promise.resolve({ results: favoritedItemIds, total }) + ], + [ + matchers.call.fn(CatalogAPI.prototype.get), + Promise.reject(error) + ] + ]) + .call.like({ + fn: CatalogAPI.prototype.get, + args: [ + { + ...options.filters, + first: 1, + ids: [favoritedItemIds[0].itemId] + } + ] + }) + .put(fetchFavoritedItemsFailure(error.message)) + .dispatch(fetchFavoritedItemsRequest(options)) + .run({ silenceTimeout: true }) + }) + }) + }) + + describe('and the marketplace-server flag is on', () => { + beforeEach(() => { + isMarketplaceFFOn = true + }) + describe('and the call to the items api fails', () => { + it('should dispatch an action signaling the failure of the handled action', () => { + return expectSaga(favoritesSaga, getIdentity) + .provide([ + [select(getListId), listId], + [select(getIsMarketplaceServerEnabled), isMarketplaceFFOn], + [select(getAddress), address], + [call(getAccountIdentity), Promise.resolve()], + [ + matchers.call.fn(FavoritesAPI.prototype.getPicksByList), + Promise.resolve({ results: favoritedItemIds, total }) + ], + [ + matchers.call.fn(CatalogAPI.prototype.get), + Promise.reject(error) + ] + ]) + .call.like({ + fn: CatalogAPI.prototype.get, + args: [ + { + ...options.filters, + first: 1, + ids: [favoritedItemIds[0].itemId] + } + ] + }) + .put(fetchFavoritedItemsFailure(error.message)) + .dispatch(fetchFavoritedItemsRequest(options)) + .run({ silenceTimeout: true }) + }) }) }) @@ -202,6 +251,7 @@ describe('when handling the request for fetching favorited items', () => { .provide([ [select(getListId), listId], [select(getAddress), address], + [select(getIsMarketplaceServerEnabled), true], [call(getAccountIdentity), Promise.resolve()], [ matchers.call.fn(FavoritesAPI.prototype.getPicksByList), @@ -256,6 +306,7 @@ describe('when handling the request for fetching favorited items', () => { .provide([ [select(getListId), listId], [select(getAddress), address], + [select(getIsMarketplaceServerEnabled), true], [call(getAccountIdentity), Promise.resolve()], [ matchers.call.fn(FavoritesAPI.prototype.getPicksByList), @@ -296,6 +347,7 @@ describe('when handling the request for fetching favorited items', () => { .provide([ [select(getListId), listId], [select(getAddress), null], + [select(getIsMarketplaceServerEnabled), true], [ matchers.call.fn(FavoritesAPI.prototype.getPicksByList), Promise.reject(error) @@ -329,6 +381,7 @@ describe('when handling the request for fetching favorited items', () => { .provide([ [select(getListId), listId], [select(getAddress), null], + [select(getIsMarketplaceServerEnabled), true], [ matchers.call.fn(FavoritesAPI.prototype.getPicksByList), Promise.resolve({ results: favoritedItemIds, total }) @@ -367,6 +420,7 @@ describe('when handling the request for fetching favorited items', () => { .provide([ [select(getListId), listId], [select(getAddress), null], + [select(getIsMarketplaceServerEnabled), true], [ matchers.call.fn(FavoritesAPI.prototype.getPicksByList), Promise.resolve({ results: favoritedItemIds, total }) @@ -420,6 +474,7 @@ describe('when handling the request for fetching favorited items', () => { .provide([ [select(getListId), listId], [select(getAddress), null], + [select(getIsMarketplaceServerEnabled), true], [ matchers.call.fn(FavoritesAPI.prototype.getPicksByList), { results: favoritedItemIds, total } @@ -611,11 +666,12 @@ describe('when handling the request for fetching lists', () => { ] }) - describe('and there are not items in the state', () => { + describe('and there are no items in the state', () => { it('should dispatch an action signaling the success of the handled action', () => { return expectSaga(favoritesSaga, getIdentity) .provide([ [call(getAccountIdentity), Promise.resolve()], + [select(getIsMarketplaceServerEnabled), true], [ matchers.call.fn(FavoritesAPI.prototype.getLists), Promise.resolve({ results: lists, total }) @@ -660,6 +716,7 @@ describe('when handling the request for fetching lists', () => { return expectSaga(favoritesSaga, getIdentity) .provide([ [call(getAccountIdentity), Promise.resolve()], + [select(getIsMarketplaceServerEnabled), true], [ matchers.call.fn(FavoritesAPI.prototype.getLists), Promise.resolve({ results: lists, total }) @@ -757,6 +814,7 @@ describe('when handling the request for fetching lists', () => { return expectSaga(favoritesSaga, getIdentity) .provide([ [call(getAccountIdentity), Promise.resolve()], + [select(getIsMarketplaceServerEnabled), true], [ matchers.call.fn(FavoritesAPI.prototype.getLists), Promise.resolve({ results: lists, total }) @@ -804,6 +862,7 @@ describe('when handling the request for fetching lists', () => { return expectSaga(favoritesSaga, getIdentity) .provide([ [call(getAccountIdentity), Promise.resolve()], + [select(getIsMarketplaceServerEnabled), true], [ matchers.call.fn(FavoritesAPI.prototype.getLists), Promise.resolve({ results: lists, total }) @@ -1034,6 +1093,7 @@ describe('when handling the request for getting a list', () => { matchers.call.fn(FavoritesAPI.prototype.getList), Promise.resolve(list) ], + [select(getIsMarketplaceServerEnabled), true], [select(getItemsData), {}], [ matchers.call.fn(CatalogAPI.prototype.get), @@ -1078,6 +1138,7 @@ describe('when handling the request for getting a list', () => { matchers.call.fn(FavoritesAPI.prototype.getList), Promise.resolve(list) ], + [select(getIsMarketplaceServerEnabled), true], [select(getItemsData), { anotherItemId: {} }], [ matchers.call.fn(CatalogAPI.prototype.get), diff --git a/webapp/src/modules/favorites/sagas.ts b/webapp/src/modules/favorites/sagas.ts index 92babedbd0..c8c020f66d 100644 --- a/webapp/src/modules/favorites/sagas.ts +++ b/webapp/src/modules/favorites/sagas.ts @@ -23,7 +23,7 @@ import { getIdentity as getAccountIdentity } from '../identity/utils' import { CatalogAPI } from '../vendor/decentraland/catalog/api' import { retryParams } from '../vendor/decentraland/utils' import { getAddress } from '../wallet/selectors' -import { NFT_SERVER_URL } from '../vendor/decentraland' +import { MARKETPLACE_SERVER_URL, NFT_SERVER_URL } from '../vendor/decentraland' import { locations } from '../routing/locations' import { SortDirection } from '../routing/types' import { ListsSortBy } from '../vendor/decentraland/favorites/types' @@ -83,6 +83,7 @@ import { import { convertListsBrowseSortByIntoApiSortBy } from './utils' import { List } from './types' import { getData as getItemsData } from '../item/selectors' +import { getIsMarketplaceServerEnabled } from '../features/selectors' export function* favoritesSaga(getIdentity: () => AuthIdentity | undefined) { const API_OPTS = { @@ -95,6 +96,10 @@ export function* favoritesSaga(getIdentity: () => AuthIdentity | undefined) { API_OPTS ) const catalogAPI = new CatalogAPI(NFT_SERVER_URL, API_OPTS) + const marketplaceServerCatalogAPI = new CatalogAPI( + MARKETPLACE_SERVER_URL, + API_OPTS + ) yield takeEvery( FETCH_FAVORITED_ITEMS_REQUEST, @@ -114,6 +119,13 @@ export function* favoritesSaga(getIdentity: () => AuthIdentity | undefined) { handleBulkPickSuccessOrFailure ) + function* getCatalogAPI() { + const isMarketplaceServerEnabled: boolean = yield select( + getIsMarketplaceServerEnabled + ) + return isMarketplaceServerEnabled ? marketplaceServerCatalogAPI : catalogAPI + } + function* fetchPreviewItems(previewListsItemIds: string[]) { let previewItems: Item[] = [] @@ -127,10 +139,8 @@ export function* favoritesSaga(getIdentity: () => AuthIdentity | undefined) { ids: previewListsItemIds } - const result: { data: Item[] } = yield call( - [catalogAPI, 'get'], - itemFilters - ) + const api: CatalogAPI = yield call(getCatalogAPI) + const result: { data: Item[] } = yield call([api, 'get'], itemFilters) previewItems = result.data } } @@ -173,9 +183,11 @@ export function* favoritesSaga(getIdentity: () => AuthIdentity | undefined) { filters: optionsFilters } + const api: CatalogAPI = yield call(getCatalogAPI) + if (results.length > 0) { const result: { data: Item[] } = yield call( - [catalogAPI, 'get'], + [api, 'get'], optionsFilters ) items = result.data diff --git a/webapp/src/modules/features/selectors.ts b/webapp/src/modules/features/selectors.ts index c61ce44e67..a767595d40 100644 --- a/webapp/src/modules/features/selectors.ts +++ b/webapp/src/modules/features/selectors.ts @@ -206,3 +206,13 @@ export const getIsNewNavbarDropdownEnabled = (state: RootState) => { } return false } +export const getIsMarketplaceServerEnabled = (state: RootState) => { + if (hasLoadedInitialFlags(state)) { + return getIsFeatureEnabled( + state, + ApplicationName.MARKETPLACE, + FeatureName.MARKETPLACE_SERVER + ) + } + return false +} diff --git a/webapp/src/modules/features/types.ts b/webapp/src/modules/features/types.ts index d1c34cdf67..a0ba6e4503 100644 --- a/webapp/src/modules/features/types.ts +++ b/webapp/src/modules/features/types.ts @@ -14,8 +14,9 @@ export enum FeatureName { MAP_VIEW_FILTERS = 'map-view-filters', RENTAL_PRICE_FILTER_CHART = 'rental-price-fitler-chart', HANDS_CATEGORY = 'hands-category', - SMART_WEARABLES_FTU = 'smart-wearables-ftu', EMOTES_V2 = 'emotes-2.0', EMOTES_V2_FTU = 'emotes-2.0-ftu', - NEW_NAVBAR_DROPDOWN = 'new-navbar-dropdown' + NEW_NAVBAR_DROPDOWN = 'new-navbar-dropdown', + SMART_WEARABLES_FTU = 'smart-wearables-ftu', + MARKETPLACE_SERVER = 'marketplace-server' } diff --git a/webapp/src/modules/features/utils.spec.ts b/webapp/src/modules/features/utils.spec.ts new file mode 100644 index 0000000000..ffe70e3ecf --- /dev/null +++ b/webapp/src/modules/features/utils.spec.ts @@ -0,0 +1,32 @@ +import { expectSaga } from 'redux-saga-test-plan' +import { select } from 'redux-saga/effects' +import { isLoadingFeatureFlags } from 'decentraland-dapps/dist/modules/features/selectors' +import { + FETCH_APPLICATION_FEATURES_FAILURE, + FETCH_APPLICATION_FEATURES_SUCCESS +} from 'decentraland-dapps/dist/modules/features/actions' +import { waitForFeatureFlagsToBeLoaded } from './utils' + +describe('waitForFeatureFlagsToBeLoaded Util', () => { + it('should do nothing if feature flags are already loaded', () => { + return expectSaga(waitForFeatureFlagsToBeLoaded) + .provide([[select(isLoadingFeatureFlags), false]]) + .not.take(FETCH_APPLICATION_FEATURES_SUCCESS) + .not.take(FETCH_APPLICATION_FEATURES_FAILURE) + .run() + }) + + it('should wait for FETCH_APPLICATION_FEATURES_SUCCESS if feature flags are being fetched', () => { + return expectSaga(waitForFeatureFlagsToBeLoaded) + .provide([[select(isLoadingFeatureFlags), true]]) + .take(FETCH_APPLICATION_FEATURES_SUCCESS) + .run() + }) + + it('should wait for FETCH_APPLICATION_FEATURES_FAILURE if feature flags are being fetched and there is an error', () => { + return expectSaga(waitForFeatureFlagsToBeLoaded) + .provide([[select(isLoadingFeatureFlags), true]]) + .take(FETCH_APPLICATION_FEATURES_FAILURE) + .run() + }) +}) diff --git a/webapp/src/modules/features/utils.ts b/webapp/src/modules/features/utils.ts new file mode 100644 index 0000000000..9b2f7b4b85 --- /dev/null +++ b/webapp/src/modules/features/utils.ts @@ -0,0 +1,16 @@ +import { race, select, take } from 'redux-saga/effects' +import { + FETCH_APPLICATION_FEATURES_FAILURE, + FETCH_APPLICATION_FEATURES_SUCCESS +} from 'decentraland-dapps/dist/modules/features/actions' +import { isLoadingFeatureFlags } from 'decentraland-dapps/dist/modules/features/selectors' + +export function* waitForFeatureFlagsToBeLoaded() { + const isFetchingFeatureFlags: boolean = yield select(isLoadingFeatureFlags) + if (isFetchingFeatureFlags) { + yield race({ + success: take(FETCH_APPLICATION_FEATURES_SUCCESS), + failure: take(FETCH_APPLICATION_FEATURES_FAILURE) + }) + } +} diff --git a/webapp/src/modules/item/sagas.spec.ts b/webapp/src/modules/item/sagas.spec.ts index 8a790b3afb..86c7d9755c 100644 --- a/webapp/src/modules/item/sagas.spec.ts +++ b/webapp/src/modules/item/sagas.spec.ts @@ -51,6 +51,8 @@ import { CANCEL_FETCH_ITEMS, itemSaga } from './sagas' import { getData as getItems } from './selectors' import { getItem } from './utils' import { ItemBrowseOptions } from './types' +import { getIsMarketplaceServerEnabled } from '../features/selectors' +import { waitForFeatureFlagsToBeLoaded } from '../features/utils' const item = { itemId: 'anItemId', @@ -432,10 +434,14 @@ describe('when handling the fetch items request action', () => { return expectSaga(itemSaga, getIdentity) .provide([ [ - matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), + matchers.call.fn( + waitForWalletConnectionAndIdentityIfConnecting + ), undefined ], + [matchers.call.fn(waitForFeatureFlagsToBeLoaded), undefined], [select(getWallet), wallet], + [select(getIsMarketplaceServerEnabled), true], [select(getLocation), { pathname }], { call(effect, next) { @@ -487,10 +493,14 @@ describe('when handling the fetch items request action', () => { return expectSaga(itemSaga, getIdentity) .provide([ [ - matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), + matchers.call.fn( + waitForWalletConnectionAndIdentityIfConnecting + ), undefined ], + [matchers.call.fn(waitForFeatureFlagsToBeLoaded), undefined], [select(getWallet), wallet], + [select(getIsMarketplaceServerEnabled), true], [select(getLocation), { pathname }], { call(effect, next) { @@ -547,9 +557,14 @@ describe('when handling the fetch items request action', () => { return expectSaga(itemSaga, getIdentity) .provide([ [matchers.call.fn(CatalogAPI.prototype.get), fetchResult], - [matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), undefined], + [ + matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), + undefined + ], + [matchers.call.fn(waitForFeatureFlagsToBeLoaded), undefined], [select(getWallet), undefined], - [select(getLocation), { pathname }] + [select(getLocation), { pathname }], + [select(getIsMarketplaceServerEnabled), false] ]) .put( fetchItemsSuccess( @@ -571,8 +586,14 @@ describe('when handling the fetch items request action', () => { .provide([ [select(getLocation), { pathname: '' }], [select(getWallet), undefined], + [select(getIsMarketplaceServerEnabled), true], + [select(getWallet), undefined], [matchers.call.fn(CatalogAPI.prototype.get), Promise.reject(anError)], - [matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), undefined] + [ + matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), + undefined + ], + [matchers.call.fn(waitForFeatureFlagsToBeLoaded), undefined] ]) .put(fetchItemsFailure(anError.message, itemBrowseOptions)) .dispatch(fetchItemsRequest(itemBrowseOptions)) @@ -586,7 +607,10 @@ describe('when handling the fetch items request action', () => { return expectSaga(itemSaga, getIdentity) .provide([ [matchers.call.fn(ItemAPI.prototype.getOne), item], - [matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), undefined] + [ + matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), + undefined + ] ]) .put(fetchItemSuccess(item)) .put(fetchSmartWearableRequiredPermissionsRequest(item)) @@ -603,7 +627,10 @@ describe('when handling the fetch items request action', () => { matchers.call.fn(ItemAPI.prototype.getOne), Promise.reject(anError) ], - [matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), undefined] + [ + matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), + undefined + ] ]) .put( fetchItemFailure(item.contractAddress, item.itemId, anError.message) @@ -635,9 +662,13 @@ describe('when handling the fetch trending items request action', () => { it('should dispatch a successful action with the fetched trending items', () => { return expectSaga(itemSaga, getIdentity) .provide([ + [select(getIsMarketplaceServerEnabled), true], [matchers.call.fn(ItemAPI.prototype.getTrendings), fetchResult], [matchers.call.fn(CatalogAPI.prototype.get), fetchResult], - [matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), undefined] + [ + matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), + undefined + ] ]) .put(fetchTrendingItemsSuccess(fetchResult.data)) .dispatch(fetchTrendingItemsRequest()) @@ -651,8 +682,12 @@ describe('when handling the fetch trending items request action', () => { it('should dispatch a successful action with the fetched trending items', () => { return expectSaga(itemSaga, getIdentity) .provide([ + // [select(getIsMarketplaceServerEnabled), true], [matchers.call.fn(ItemAPI.prototype.getTrendings), fetchResult], - [matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), undefined] + [ + matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), + undefined + ] ]) .put(fetchTrendingItemsSuccess(fetchResult.data)) .dispatch(fetchTrendingItemsRequest()) @@ -669,7 +704,10 @@ describe('when handling the fetch trending items request action', () => { matchers.call.fn(ItemAPI.prototype.getTrendings), Promise.reject(anError) ], - [matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), undefined] + [ + matchers.call.fn(waitForWalletConnectionAndIdentityIfConnecting), + undefined + ] ]) .put(fetchTrendingItemsFailure(anError.message)) .dispatch(fetchTrendingItemsRequest()) diff --git a/webapp/src/modules/item/sagas.ts b/webapp/src/modules/item/sagas.ts index 8e938152e1..8a9ea498b1 100644 --- a/webapp/src/modules/item/sagas.ts +++ b/webapp/src/modules/item/sagas.ts @@ -33,6 +33,9 @@ import { retryParams } from '../vendor/decentraland/utils' import { CatalogAPI } from '../vendor/decentraland/catalog/api' import { locations } from '../routing/locations' import { fetchSmartWearableRequiredPermissionsRequest } from '../asset/actions' +import { MARKETPLACE_SERVER_URL } from '../vendor/decentraland' +import { getIsMarketplaceServerEnabled } from '../features/selectors' +import { waitForFeatureFlagsToBeLoaded } from '../features/utils' import { buyItemFailure, BuyItemRequestAction, @@ -78,6 +81,10 @@ export function* itemSaga(getIdentity: () => AuthIdentity | undefined) { identity: getIdentity } const itemAPI = new ItemAPI(NFT_SERVER_URL, API_OPTS) + const marketplaceServerCatalogAPI = new CatalogAPI( + MARKETPLACE_SERVER_URL, + API_OPTS + ) const catalogAPI = new CatalogAPI(NFT_SERVER_URL, API_OPTS) yield fork(() => takeLatestByPath(FETCH_ITEMS_REQUEST, locations.browse())) @@ -130,8 +137,14 @@ export function* itemSaga(getIdentity: () => AuthIdentity | undefined) { } const ids = data.map(item => item.id) + const isMarketplaceServerEnabled: boolean = yield select( + getIsMarketplaceServerEnabled + ) + const api = isMarketplaceServerEnabled + ? marketplaceServerCatalogAPI + : catalogAPI const { data: itemData }: { data: Item[]; total: number } = yield call( - [catalogAPI, 'get'], + [api, 'get'], { ids } @@ -173,7 +186,14 @@ export function* itemSaga(getIdentity: () => AuthIdentity | undefined) { try { // If the wallet is getting connected, wait until it finishes to fetch the wallet and generate the identity so it can fetch them with authentication yield call(waitForWalletConnectionAndIdentityIfConnecting) - const api = isCatalogView(view) ? catalogAPI : itemAPI + yield call(waitForFeatureFlagsToBeLoaded) + const isMarketplaceServerEnabled: boolean = yield select( + getIsMarketplaceServerEnabled + ) + const catalogViewAPI = isMarketplaceServerEnabled + ? marketplaceServerCatalogAPI + : catalogAPI + const api = isCatalogView(view) ? catalogViewAPI : itemAPI const { data, total }: { data: Item[]; total: number } = yield call( [api, 'get'], filters diff --git a/webapp/src/modules/routing/search.ts b/webapp/src/modules/routing/search.ts index 7a032af172..2d05856aba 100644 --- a/webapp/src/modules/routing/search.ts +++ b/webapp/src/modules/routing/search.ts @@ -271,7 +271,7 @@ export function getMarketAssetTypeFromCategory(category: NFTCategory) { export function getSearchSection(category: WearableCategory | EmoteCategory) { for (const section of Object.values(Section)) { const sectionCategory = Object.values(EmoteCategory).includes( - category as EmoteCategory + category.toLocaleLowerCase() as EmoteCategory //@TODO: Remove toLowerCase() when the indexer save them as lowercase ) ? getSearchEmoteCategory(section) : getSearchWearableCategory(section) diff --git a/webapp/src/modules/vendor/decentraland/nft/api.ts b/webapp/src/modules/vendor/decentraland/nft/api.ts index 455b6ce66f..0e4693085d 100644 --- a/webapp/src/modules/vendor/decentraland/nft/api.ts +++ b/webapp/src/modules/vendor/decentraland/nft/api.ts @@ -9,11 +9,9 @@ import { getNFTSortBy } from '../../../routing/search' import { AssetType } from '../../../asset/types' import { config } from '../../../../config' import { retryParams } from '../utils' -import { - OwnersFilters, - OwnersResponse -} from './types' +import { OwnersFilters, OwnersResponse } from './types' +export const MARKETPLACE_SERVER_URL = config.get('MARKETPLACE_SERVER_URL')! export const NFT_SERVER_URL = config.get('NFT_SERVER_URL')! export enum PriceFilterExtraOption {