Basic Usage
Configuring Equippability

Configuring-equipability

Equippable & Composable is the most advanced module, as it requires both MultiAsset and Nestable ones. After you have deployed your NFT contract, you may add new equippable and/or composable assets. Equippable assets can receive children to be equipped or be equipped into a parent, or both.

Pre-requisites for equipment to be valid

For a token to be equippable there are a series of conditions that need to be met. They are tailored to ensure that only assets from collections meant to be equipped are possible:

  1. The slot must be defined in the catalog and it must be configured so that child collection can use it.
  2. The parent token must have an asset with slot parts.
  3. The child token must have an asset that is equippable into the parent's slot. This is done through the equippableGroupId.

Equippable Group Id

To better understand the equippableGroupId paramater let's consider the following example. Let's say you have a collection of Soldiers and a collection of Weapons. You want to allow the Soldiers to equip the Weapons in either hand. You would need to:

  1. Create a catalog with a slot WL for the left hand and a slot WR for the right hand. You also configure this slot to be usable by the Weapons collection. This can be achieved by using when creating part with either addPart or addPartList, or later through addEquippableAddresses, setEquippableAddresses or setEquippableToAll. See the Catalog section for more details.
  2. The parent token must have an asset which includes WL and WR in its partIds array. You do this exclusively with the addEquippableAssetEntry function.
  3. Each Weapon NFT will have 2 assets, one for the left hand and one for the right hand. All assets meant for the left hand will have the same equippableGroupId:EGL and all assets meant for the right hand will have the same equippableGroupId:EGR. You need to set the equippableGroupId when adding the asset with the addEquippableAssetEntry function and you configure each equippableGroupId to be equippable into the left and right hand slots of the Soldier collection, respectively. This can be achieved by using the setValidParentForEquippableGroup function.

With these conditions met, any NFT from the Weapons collection, nested into any NFT from the Soldiers collection will be equippable into the left or right hand slots.

These are the operations you may need to perform when working with equippable and composable assets:

Writing operations

  1. Adding a new equippable/composable asset.
  2. Equipping a child asset.
  3. Unequipping a child asset.
  4. Set valid parent for equippable group.

Adding a new equippable/composable asset

In our ready to use implementations, adding a new asset can be performed by the collection owner or a contributor.

For an asset to be equippable into a parent asset you need to use the addEquippableAssetEntry function instead of addAssetEntry and assign a non zero equippableGroupId to it.

For an asset to be composable you need to use the addEquippableAssetEntry function instead of addAssetEntry and assign a catalogAddress and non empty partIds array to it.

The asset is added to the collection and can be later added into any token. Our implementations take care of assigning a unique Id, starting by 1. For more details on the contents of the metadata see the metadata section.

// For equippable into parent
const equippableGroupId = 1;
const catalogAddress = '0x0000000000000000000000000000000000000000'; // Unless also composable
const metadataURI = 'ipfs://...';
const partIds = []; // Unless also composable
 
// For composables
const equippableGroupId = 0; // Unless you want it to be equippable into a parent.
const catalogAddress = '0x...';
const metadataURI = 'ipfs://...';
const partIds = [1, 2, 3];
 
await contract.addEquippableAssetEntry(
    equippableGroupId,
    catalogAddress,
    metadataURI,
    partIds
);

Equipping a child asset

Used to equip a child into a token.

const parentId = 1;
const childId = 10;
const parentAssetId = 5;
const childAssetId = 15;
const slotPartId = 1;
 
// Find childIndex on parent's active children
const childrenIds = (await parentContract.childrenOf(parentId)).map(
    (child) => child.tokenId.toNumber()
)
const childIndex = childrenIds.indexOf(childId)
 
const data = {
    tokenId: parentId,
    childIndex,
    assetId: parentAssetId,
    slotPartId,
    childAssetId
}
await parentContract.equip(data);

Unequipping a child asset

Used to unequip child from parent token.

const parentId = 1;
const parentAssetId = 5;
const slotPartId = 1;
 
await parentContract.unequip(parentId, parentAssetId, slotPartId);

Set valid parent for equippable group

Used to declare that the assets belonging to a given equippableGroupId are equippable into the Slot with partId on the collection at the specified parentAddress. Every child NFT which has an asset belonging to the equippable group will be equippable into the slot of the parent NFT.

const equippableGroupId = 1;
const parentAddress = '0x...';
const partId = 1;
 
await childContract.setValidParentForEquippableGroup(
    equippableGroupId,
    parentAddress,
    partId
);

Reading operations

  1. Check if a child is equipped.
  2. Check if a child is equippable in a slot
  3. Get asset and equippable data
  4. Get equipment

Check if a child is equipped

Used to check whether the token has a given child equipped. An equipped child will prevent the child token to be unnested.

const parentId = 1;
const childId = 10;
const childAddress = '0x...';
 
const isEquipped = await parentContract.isChildEquipped(
    parentId,
    childAddress,
    childId
);

Check if a child is equippable in a slot

Used to verify whether a token can be equipped into a given parent's slot. This is called from child contract.

const parentAddress = '0x...';
const parentId = 1;
const assetId = 10;
const slotId = 1;
 
const canBeEquipped = await childContract.canTokenBeEquippedWithAssetIntoSlot(
    parentAddress,
    parentId,
    assetId,
    slotId
);

Get asset and equippable data

Used to get the asset and equippable data associated with given assetId. The metadata returned is the same as the one returned by the getAssetMetadata function.

const tokenId = 1;
const assetId = 10;
 
const {
    metadataURI,
    equippableGroupId,
    catalogAddress,
    partIds
} = await contract.getAssetAndEquippableData(tokenId, assetId);

Get equipment

Used to get the Equipment data for a token, catalog and slot combination. It returns an empty struct if no equipment is found.

const tokenId = 1;
const targetCatalogAddress = '0x...';
const slotPartId = 1;
 
const equipment = await parentContract.getEquipment(
    tokenId,
    targetCatalogAddress,
    slotPartId
);
// equipment = [
//     assetId,
//     childAssetId,
//     childId,
//     childEquippableAddress
// ]