Skip to content

Commit

Permalink
fix: third-party wearables on outfits (#335)
Browse files Browse the repository at this point in the history
  • Loading branch information
aleortega authored Jun 4, 2024
1 parent 3c3221e commit bec4984
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 10 deletions.
11 changes: 5 additions & 6 deletions src/adapters/profiles.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { AppComponents, ProfileMetadata } from '../types'
import { Avatar, Entity, Snapshots } from '@dcl/schemas'
import { createTPWOwnershipChecker } from '../ports/ownership-checker/tpw-ownership-checker'
import { parseUrn } from '@dcl/urn-resolver'
import { splitUrnAndTokenId } from '../logic/utils'
import { createTPWOwnershipChecker } from '../ports/ownership-checker/tpw-ownership-checker'

function isBaseWearable(wearable: string): boolean {
return wearable.includes('base-avatars')
Expand Down Expand Up @@ -91,8 +91,7 @@ export async function createProfilesComponent(
}

profileEntities = profileEntities.filter((entity) => !!entity.metadata)

const tpwOwnershipChecker = createTPWOwnershipChecker(components)
const thirdPartyWearablesOwnershipChecker = createTPWOwnershipChecker(components)

return await Promise.all(
profileEntities.map(async (entity) => {
Expand All @@ -118,16 +117,16 @@ export async function createProfilesComponent(
}
}
}
tpwOwnershipChecker.addNFTsForAddress(ethAddress, wearables)
thirdPartyWearablesOwnershipChecker.addNFTsForAddress(ethAddress, wearables)

const [ownedWearables, ownedEmotes, ownedNames] = await Promise.all([
wearablesFetcher.fetchOwnedElements(ethAddress),
emotesFetcher.fetchOwnedElements(ethAddress),
namesFetcher.fetchOwnedElements(ethAddress),
tpwOwnershipChecker.checkNFTsOwnership()
thirdPartyWearablesOwnershipChecker.checkNFTsOwnership()
])

const thirdPartyWearables = tpwOwnershipChecker.getOwnedNFTsForAddress(ethAddress)
const thirdPartyWearables = thirdPartyWearablesOwnershipChecker.getOwnedNFTsForAddress(ethAddress)

const avatars: Avatar[] = []
for (const avatar of metadata.avatars) {
Expand Down
11 changes: 10 additions & 1 deletion src/controllers/handlers/outfits-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,16 @@ import { Entity } from '@dcl/schemas'

export async function outfitsHandler(
context: HandlerContextWithPath<
'metrics' | 'content' | 'theGraph' | 'config' | 'fetch' | 'ownershipCaches' | 'wearablesFetcher' | 'namesFetcher',
| 'metrics'
| 'content'
| 'theGraph'
| 'config'
| 'fetch'
| 'ownershipCaches'
| 'wearablesFetcher'
| 'namesFetcher'
| 'thirdPartyProvidersStorage'
| 'logs',
'/outfits/:id'
>
): Promise<{ status: 200; body: Entity }> {
Expand Down
28 changes: 27 additions & 1 deletion src/logic/outfits.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import { Outfit, Outfits } from '@dcl/schemas'
import { AppComponents, OnChainWearable, TypedEntity } from '../types'
import { splitUrnAndTokenId } from './utils'
import { createTPWOwnershipChecker } from '../ports/ownership-checker/tpw-ownership-checker'

export async function getOutfits(
components: Pick<
AppComponents,
'metrics' | 'content' | 'theGraph' | 'config' | 'fetch' | 'ownershipCaches' | 'wearablesFetcher' | 'namesFetcher'
| 'metrics'
| 'content'
| 'theGraph'
| 'config'
| 'fetch'
| 'ownershipCaches'
| 'wearablesFetcher'
| 'namesFetcher'
| 'thirdPartyProvidersStorage'
| 'logs'
>,
ethAddress: string
): Promise<TypedEntity<Outfits> | undefined> {
const { config, wearablesFetcher, namesFetcher, content } = components
const ensureERC721 = (await config.getString('ENSURE_ERC_721')) !== 'false'
const thirdPartyWearablesOwnershipChecker = createTPWOwnershipChecker(components)

const outfitsEntities: TypedEntity<Outfits>[] = await content.fetchEntitiesByPointers([`${ethAddress}:outfits`])

Expand All @@ -32,12 +43,17 @@ export async function getOutfits(

for (const outfit of metadata.outfits) {
const wearables: string[] = []
const thirdPartyWearables: string[] = []
let allWearablesOwned = true

for (const wearable of outfit.outfit.wearables) {
if (wearable.includes('off-chain') || wearable.includes('base-avatars')) {
wearables.push(wearable)
continue
} else if (wearable.includes('collections-thirdparty')) {
wearables.push(wearable)
thirdPartyWearables.push(wearable)
continue
}

const { urn, tokenId } = splitUrnAndTokenId(wearable)
Expand All @@ -60,6 +76,16 @@ export async function getOutfits(
}
}

if (thirdPartyWearables.length > 0) {
thirdPartyWearablesOwnershipChecker.addNFTsForAddress(ethAddress, thirdPartyWearables)
await thirdPartyWearablesOwnershipChecker.checkNFTsOwnership()
const thirdPartyWearablesOwned = thirdPartyWearablesOwnershipChecker.getOwnedNFTsForAddress(ethAddress)

allWearablesOwned = thirdPartyWearables.every((tpWearable: string) =>
thirdPartyWearablesOwned.includes(tpWearable)
)
}

if (allWearablesOwned) {
fullyOwnedOutfits.push({ ...outfit, outfit: { ...outfit.outfit, wearables } })
}
Expand Down
2 changes: 1 addition & 1 deletion src/logic/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export async function parseUrn(urn: string) {
export function splitUrnAndTokenId(urnReceived: string) {
const urnLength = urnReceived.split(':').length

if (urnLength === 7) {
if (urnLength === 7 && !urnReceived.includes('collections-thirdparty')) {
const lastColonIndex = urnReceived.lastIndexOf(':')
const urnValue = urnReceived.slice(0, lastColonIndex)
return { urn: urnValue, tokenId: urnReceived.slice(lastColonIndex + 1) }
Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export type ProfileMetadata = Profile & {

export interface NFTsOwnershipChecker {
addNFTsForAddress: (address: string, nfts: string[]) => void
checkNFTsOwnership: () => void
checkNFTsOwnership: () => Promise<void>
getOwnedNFTsForAddress: (address: string) => string[]
}

Expand Down

0 comments on commit bec4984

Please sign in to comment.