> ## Documentation Index
> Fetch the complete documentation index at: https://docs.immutable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Crafting

Let players combine existing NFTs to create new ones—a core mechanic for progression and engagement in games.

## Why Use Crafting?

<AccordionGroup>
  <Accordion title="Player Engagement" icon="gamepad">
    Crafting drives collection and trading behaviour. Players actively hunt for ingredients, creating demand across your economy.
  </Accordion>

  <Accordion title="Asset Sinks" icon="fire">
    Burning inputs removes items from circulation, maintaining scarcity and value in your game economy.
  </Accordion>

  <Accordion title="Progression Depth" icon="arrow-trend-up">
    Multi-step recipes create meaningful goals. Players feel invested when they craft rare items.
  </Accordion>
</AccordionGroup>

## How It Works

<Steps>
  <Step title="Player Selects Items">
    Player chooses NFTs to combine from their inventory
  </Step>

  <Step title="Backend Validates">
    Your server verifies ownership and recipe validity
  </Step>

  <Step title="Burn Inputs">
    Transfer input NFTs to burn address
  </Step>

  <Step title="Mint Output">
    Create new NFT for player via [Minting API](/docs/products/asset-contracts/minting-api)
  </Step>
</Steps>

## Recipe System

Define recipes that map inputs to outputs:

```typescript theme={null}
const recipes = [
  {
    id: 'iron_sword',
    inputs: [
      { contract: MATERIALS, trait: { type: 'Iron Ore' }, count: 2 },
      { contract: MATERIALS, trait: { type: 'Wood' }, count: 1 },
    ],
    output: {
      name: 'Iron Sword',
      attributes: [{ trait_type: 'Damage', value: 10 }],
    },
  },
  {
    id: 'steel_sword',
    inputs: [
      { contract: WEAPONS, trait: { type: 'Iron Sword' }, count: 1 },
      { contract: MATERIALS, trait: { type: 'Steel Ingot' }, count: 2 },
    ],
    output: {
      name: 'Steel Sword',
      attributes: [{ trait_type: 'Damage', value: 25 }],
    },
  },
];
```

## Implementation

```typescript theme={null}
const BURN_ADDRESS = '0x000000000000000000000000000000000000dEaD';

app.post('/craft', async (req, res) => {
  const { recipeId, inputTokenIds, playerAddress } = req.body;
  const recipe = recipes.find(r => r.id === recipeId);
  
  if (!recipe) {
    return res.status(400).json({ error: 'Invalid recipe' });
  }
  
  // Verify ownership of all inputs
  for (const tokenId of inputTokenIds) {
    const owner = await nftContract.ownerOf(tokenId);
    if (owner.toLowerCase() !== playerAddress.toLowerCase()) {
      return res.status(403).json({ error: 'Not owner of input' });
    }
  }
  
  // Verify inputs match recipe requirements
  // ... validation logic
  
  // Burn inputs
  for (const tokenId of inputTokenIds) {
    await nftContract.transferFrom(playerAddress, BURN_ADDRESS, tokenId);
  }
  
  // Mint output via Minting API
  const outputId = generateTokenId();
  await mintNFT(playerAddress, outputId, recipe.output);
  
  res.json({ success: true, outputId });
});
```

## Upgrades

Enhance existing items by burning materials:

```typescript theme={null}
async function upgradeItem(tokenId: string, materialsUsed: string[]) {
  const nft = await getNFT(tokenId);
  const level = nft.attributes.find(a => a.trait_type === 'Level')?.value || 1;
  
  // Burn material NFTs
  for (const materialId of materialsUsed) {
    await burnNFT(materialId);
  }
  
  // Update metadata via Minting API refresh
  await refreshMetadata(tokenId, {
    ...nft.metadata,
    attributes: nft.attributes.map(a => 
      a.trait_type === 'Level' ? { ...a, value: level + 1 } : a
    ),
  });
}
```

## Design Tips

| Pattern           | Description                            |
| ----------------- | -------------------------------------- |
| **Deterministic** | Same inputs always produce same output |
| **Probabilistic** | Random chance for rare outcomes        |
| **Time-gated**    | Crafting takes time to complete        |
| **Progressive**   | Multi-step recipes for advanced items  |

<Info>
  Keep crafting server-side to prevent exploitation. Only mint outputs after verifying ownership and burning inputs.
</Info>

## Next Steps

<CardGroup cols={3}>
  <Card title="Minting API" icon="wand-magic-sparkles" href="/docs/products/asset-contracts/minting-api">
    Learn about the Minting API
  </Card>

  <Card title="ERC-721" icon="image" href="/docs/products/asset-contracts/erc721">
    Deploy NFT contracts
  </Card>

  <Card title="ERC-1155" icon="layer-group" href="/docs/products/asset-contracts/erc1155">
    Use multi-token contracts
  </Card>
</CardGroup>
