ADR-202: Linked Wearables Implementation

More details about this document
Latest published version:
https://adr.decentraland.org/adr/ADR-202
Authors:
pentreathm
mgoldman
nachomazzara
lautaropetaccio
Feedback:
GitHub decentraland/adr (pull requests, new issue, open issues)
Edit this documentation:
GitHub View commits View commits on githistory.xyz

Abstract

This decision aims to enhance the LinkedWearables system by addressing slow ownership verification and content creation challenges. Currently, reliance on third-party APIs for NFT ownership verification leads to delays and lacks historical validation during Catalyst synchronization.

Context, Reach & Prioritization

To foster greater adoption and streamline the cost and maintenance of LinkedWearables, it is necessary to implement a new process and architecture capable of adapting to the demand while preventing any potential performance issues for the client. Additionally, it will enhance the user experience by allowing users to view all their LinkedWearables directly on the backpack, without needing to pre-select collections from a dropdown menu.

Decision

LinkedWearables in Decentraland are wearables exclusively granted to owners of specific NFTs. While the wearables themselves cannot be traded, the underlying NFTs can. Verifying ownership of these wearables necessitated a service to provide the owner of the represented NFTs. To streamline this process, a new system of URNs for LinkedWearables and wearable metadata will be introduced. These URNs and metadata will comprehensively describe both the Decentraland wearable and its corresponding NFT, enabling on-chain verification of NFT ownership, thereby eliminating the reliance on third party APIs.

Furthermore, the relationship between Decentraland Wearables and their associated NFT collection items will be recorded within the wearable entity's metadata. This ensures that when a LinkedWearable is submitted to the Catalyst node, it includes details about the represented NFT collections items.

This decision eliminates the need for third parties to implement and maintain API resolvers and utilizes decentralized mechanisms for both content storage and ownership validation.

LinkedWearable Deployments

When uploading a LinkedWearable to a Catalyst node, the pointer URN and the mapping configuration between the Decentraland wearable and the NFT collection items must be specified.

Wearables Pointers for Linked Wearables Deployments: The new URN system maintains the existing LinkedWearables pointer when deploying a new linked wearable, allowing seamless migration of old content to the new LinkedWearable system. The previous entity will become inactive and be replaced by the updated version. A critical addition is the mapping of the wearable to its associated NFT collection items, which must be included in the wearable entity during deployment. Several use cases for this mapping are outlined below, with more detailed information available in the schemas repository.

Wearables Mappings: A Decentraland wearable can be linked to one or multiple NFT collection items, meaning that ownership of the specified NFTs grant the user access to the corresponding wearable in Decentraland. The term mapping describes the relationship between a Decentraland wearable and its associated NFTs, resulting in several possible use cases described below.

A Decentraland wearable is granted to a user who:

The mappings configuration supports lists of contracts by chain and multiple sets of collection items, as long as the sets do not overlap with each other in the same collection. This flexibility can accommodate any use case required by a third party. A Decentraland wearable can be linked/mapped to single or multiple items across one or many NFT collections on different chains.

The examples below are mapping configurations within a wearable entity that represent various use cases. This information is sent to the Catalyst during the deployment of the wearable entity.

  {
    "mappings": {
      "matic": {        
        "0x1234567890abcdef1234567890abcdef12345678": [
          {
            "type": "single",
            "id": "1"
          }
        ]
      }
    }
  }
 {
   "mappings": {
     "mainnet": {
       "0xabcdefabcdefabcdefabcdefabcdefabcdef12345678": [
         {
           "type": "any"
         }
       ]
     }
   }
 }
{
  "mappings": {
    "matic": {
      "0x9876543210abcdef9876543210abcdef98765432": [
        {
          "type": "multiple",
          "ids": ["3", "5", "7", "9"]            
        }
      ]
    }
  }
}
  {
    "mappings": {
      "mainnet": {
        "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef": [
          {
            "type": "range",
            "from": "10",
            "to": "20"
          }
        ]
      }
    }
  }
  {
    "mappings": {
      "matic": {
        "0x1234567890abcdef1234567890abcdef12345678": [
          {
            "type": "range",
            "from": "100",
            "to": "200"
          },
          {
            "type": "multiple",
            "ids": ["203", "207", "233"]
          }
        ]
      },
      "mainnet": {
         "0xabcdefabcdefabcdefabcdefabcdefabcdef12345678": [
          {
            "type": "any"
          }
        ]
      }
    }
  }

Profile and Outfits Deployments

The LinkedWearable entity represents sets of NFT collection items, but users own individual NFTs within those collections. When users interact with the wearable to equip it in their profile or outfit, they do so with a single item from the collection. To facilitate this, an extended URN is used to identify the specific item a user is interacting with. This extended URN begins with the identification of the wearable, as stated in the previous section, and continues with the data that identifies the NFT collection item granting the wearable. This information allows the Catalyst node to perform on-chain validations, verifying that the user's wallet owns the NFT associated with the wearable.

The use of extended URNs for the individuals items management is documented on ADR-244.

Example URN: urn:decentraland:matic:collections-thirdparty:adidas:summer2024:red-hoodie:matic:0xba0c9cf4da821dba98407cc4f9c11f6c7a5f9bbc:1

With the information from the URN, the collection contract at address 0xba0c9cf4da821dba98407cc4f9c11f6c7a5f9bbc on matic, can be queried to verify if the user equipping the wearable owns the item with id 1.

Third Party Registry

When a third party is registered, a record is added to the third party's smart contract. This record must now include the list of NFT collection contracts and their corresponding chains for which the third party will create wearables. This information is essential for the Catalyst nodes to create a backpack endpoint, retrieve all NFTs owned by a wallet across those collections, and identify any corresponding linked wearables for those NFT items.

The third parties will be registered as follow: tp:1:[thirdPartyName]:[thirdPartyDescription]:[thirdPartyContracts] where [thirdPartyContracts] is equal to [network]-[contract];[thirdPartyContracts]
for example: tp:1:my-awesome-studio:back-to-the-future:amoy-0x1d9fb685c257E74f869BA302e260C0b68f5eBB37;sepolia-0x74c78f5a4ab22f01d5fd08455cf0ff5c3367535c

Catalyst

The Catalyst node will expose an endpoint GET /explorer/:address/wearables, which will retrieve all owned wearables for a given wallet, including all LinkedWearables owned by that wallet, as specified in this ADR. Below is a sequence diagram illustrating the general implementation concept for retrieving all wearables for the backpack, with a focus on the LinkedWearables use case.

Sequence diagram of for backpack building

sequenceDiagram
Client->>Catalyst: GET /explorer/:address/wearables
Catalyst->>ThirdPartyRegistry: Get all third-party collections addresses
ThirdPartyRegistry-->>Catalyst: contractAddresses[]
Catalyst->>Alchemy: getNFTsForOwner(owner, contractAddresses[])
Alchemy-->>Catalyst: tokenIds[]
Catalyst-->>Catalyst: Calculate Wearable URN for tokenId[]
Catalyst-->>Client: owned linked wearables

When the client requests the owned wearables for a specific user, Catalyst nodes can query the third-party registry contract to obtain a list of all available NFT collection contracts that provide wearables to their holders. Using this contract information, the Catalyst node can leverage a third-party service like Alchemy to retrieve the list of token IDs owned by a wallet across these contracts. This data can then be cross-referenced with the existing wearables mappings for those collections to identify which token IDs correspond to wearables, allowing the Catalyst node to return the extended URN for each wearable.

Sequence diagram for ownership checking during profile validation

sequenceDiagram
   participant Client
   participant Catalyst
   participant Blockchain
   Client ->> Catalyst: Get Profile 0x123
   activate Catalyst
   Catalyst ->> Blockchain: Does the user 0x123 own this red shirt, this blue hat and the yellow shoes?
   Blockchain->> Catalyst: Ok: yes, no, yes
   Catalyst ->> Catalyst: Remove all non-owned wearables
   deactivate Catalyst
   Catalyst ->> Client: Ok (HTTP 200) with the Profile

When a client requests a profile from the Catalyst node, the node must sanitize the profile by removing any equipped items that are no longer owned by the user. To achieve this, the node validates the current ownership of the items on the blockchain and returns the profile with only the items that are currently owned by the user's wallet.

Deadline

Once the new implementation of LinkedWearables is fully supported, there will be a migration period to re-upload all existing LinkedWearables with the necessary mapping information. A deadline will be established for this migration. After the migration period ends and the deadline is reached, the old Third Party Resolvers API will no longer be used by the Catalyst nodes.

Date: TBD

Consequences

License

Copyright and related rights waived via CC0-1.0. Living