Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adds the trending endpoint for nfts #62

Merged
merged 14 commits into from
Jun 2, 2022

Conversation

juanmahidalgo
Copy link
Contributor

Closes #55

Copy link
Member

@cazala cazala left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just reviewed the logic and it looks okay to me, except for the fact the this is returning NFTs when i think we should return Items. The sale list is being reduced and accumulated by item id: https://github.com/decentraland/nft-server/pull/62/files#diff-1252b400db58108e959ce30a4956c10e6cd01c8034662e8cd550f6a69083ff2eR45 and then the itemId is used to find the correspondng NFts: https://github.com/decentraland/nft-server/pull/62/files#diff-1252b400db58108e959ce30a4956c10e6cd01c8034662e8cd550f6a69083ff2eR45

I think this will be misleading, because if an item sells for instance 1000 times (via mints), once aggregated the contractAddress + itemId record will have a value of 1000, and then when doing the find it will get one of the 1000 nfts and return that one. So on the homepage you will see one specific NFT that got sold once, and might not even be on sale now, instead of the Item that has all the sales and where you as a user can buy it again (mint it). So I think instead of using the nftComponent we should use instead the itemComponent and filter out sales of nfts that don't have an itemId (like the case of LANDs or names) since those sales even tho could show up by volume they might not be on sale anymore, and it's of no interest for the user browsing the trending section.

// Fetch all the nfts from those 24hs sales
const nftResults = (
// Fetch all the items from those 24hs sales
const items = (
await Promise.all(
sales.map((sale) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is going to include repeated items in the list, and do unnecessary fetchs. For instance if there are 20 sales in the last 24hs for the the same item of the same collection there are going to be 20 fetchs for that same item.

If we moved the computation of the trendingSales record that's below this block to happen first, then we could use the keys of that record to fetch the required items, like this:

// First compute the trending sales record
const trendingSales = ...

// Then use the keys to fetch the items
const items = Promise.all(
  Object.keys(trendingSales).map(key => {
    const [contractAddress, itemId] = key.split('-')
    return itemsComponent.fetch({ contractAddress, itemId })
  })
).recuce(a, b) => a.concat(b), []) // flatten

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh nice catch! yeah, it can definitely be moved after to avoid those extra fetches. Updated!


// Get trending sales by amount of sales
const trendingSales = sales.reduce((acc, sale) => {
const key = `${sale.contractAddress}-${sale.itemId}`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Watch out here: the sale.itemId could be undefined for NFTs that are not part of a collection (parcels, estates, names, and L1 wearables). Those should be skipped from the trendingSales record, ie:

const trendingSales = sales.reduce((acc, sale) => {
  if (sale.itemId) {
    const key = `${sale.contractAddress}-${sale.itemId}`
    acc[key] = (acc[key] || 0) + 1
  }
  return acc
}, {} as Record<string, number>)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes! updated to avoid that unnecessary fetch in case they don't have itemId.

Copy link
Member

@cazala cazala left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙌🏻

@@ -72,6 +72,8 @@ export function createTrendingsComponent(
// It will iterate over sales which is already ordered by volume as it was used as the SortBy parameter.
const trendingByVolume: Item[] = sales
.map((sale) => {
// console.log('sale.contractAddress: ', sale.contractAddress)
// console.log('sale.itemId: ', sale.itemId)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we remove these comments?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes! 🤦 removed!

Base automatically changed from feat/volume-endpoint to master June 1, 2022 19:10
@juanmahidalgo juanmahidalgo merged commit 17b08dc into master Jun 2, 2022
@juanmahidalgo juanmahidalgo deleted the feat/trendings-endpoint branch June 2, 2022 08:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Trending wearables
2 participants