Розробка системи крафтингу NFT

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка системи крафтингу NFT
Середній
~3-5 днів
Часті запитання

Напрямки блокчейн-розробки

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1285
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1198
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    902
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1121
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    589
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    858

Розробка системи крафтинга NFT

NFT крафтинг — механіка, при якій кілька NFT або ресурсів об'єднуються для створення нового NFT. Це одночасно sink-механізм (спалює або споживає NFT/токени) і джерело нових цінних предметів. Правильно реалізована система крафтинга створює економічний цикл і утримує гравців.

Типи крафтинга

Fusion (злиття): N токенів одного типу → 1 токен більш високого tier. Класичний приклад: 3 Common меча → 1 Rare меч. Спрощує інвентар, створює попит на низькотирові NFT.

Recipe крафтинг: конкретні комбінації матеріалів → конкретний результат. Поварська книга алхіміка: 1 Iron Ore + 2 Coal + 1 Fire Essence → Steel Ingot.

Random crafting: матеріали + randomness → результат з діапазону можливих. Ризик/награда: можна отримати legendary, можна отримати common.

Upgrade (прокачка): існуючий NFT + матеріали → той же NFT з поліпшеними атрибутами.

Smart contract реалізація

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/AccessControl.sol";

contract NFTCraftingSystem is AccessControl, VRFConsumerBaseV2Plus {
    bytes32 public constant RECIPE_MANAGER = keccak256("RECIPE_MANAGER");
    
    struct CraftingRecipe {
        uint256 recipeId;
        string name;
        // Входящі матеріали
        address[] inputContracts;   // адреси NFT контрактів матеріалів
        uint256[] inputTokenIds;    // tokenId (0 = будь-який з колекції)
        uint256[] inputAmounts;     // кількість (для ERC-1155)
        // Входящі ERC-20 токени
        address[] tokenInputs;
        uint256[] tokenAmounts;
        // Вихід
        address outputContract;
        uint256 outputTokenId;     // 0 = random з діапазону
        uint256 minOutputId;       // для random: мінімальний tokenId
        uint256 maxOutputId;       // для random: максимальний tokenId
        bool burnInputs;           // спалити або тільки споживати
        bool requiresVRF;          // потрібен ли random?
        bool isActive;
        uint256 cooldown;          // секунди між крафтингами одним адресом
    }
    
    mapping(uint256 => CraftingRecipe) public recipes;
    mapping(address => mapping(uint256 => uint256)) public lastCraftTime; // гравець → recipeId → timestamp
    mapping(uint256 => PendingCraft) public pendingCrafts; // vrfRequestId → craft
    
    struct PendingCraft {
        address crafter;
        uint256 recipeId;
        bool fulfilled;
    }
    
    function craft(uint256 recipeId, uint256[][] calldata inputTokenIds) 
        external returns (uint256 requestId) 
    {
        CraftingRecipe storage recipe = recipes[recipeId];
        require(recipe.isActive, "Recipe not active");
        
        // Cooldown перевірка
        require(
            block.timestamp >= lastCraftTime[msg.sender][recipeId] + recipe.cooldown,
            "Crafting cooldown active"
        );
        lastCraftTime[msg.sender][recipeId] = block.timestamp;
        
        // Валідуємо і забираємо матеріали
        _consumeInputMaterials(recipe, inputTokenIds);
        _consumeInputTokens(recipe);
        
        if (recipe.requiresVRF) {
            // Для випадкового крафтингу — запрошуємо VRF
            requestId = _requestRandomWords(1);
            pendingCrafts[requestId] = PendingCraft({
                crafter: msg.sender,
                recipeId: recipeId,
                fulfilled: false,
            });
            emit CraftingInitiated(msg.sender, recipeId, requestId);
        } else {
            // Детерміністичний крафтинг — мінтимо одразу
            _mintCraftingResult(msg.sender, recipe, 0);
        }
    }
    
    function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) 
        internal override 
    {
        PendingCraft storage pending = pendingCrafts[requestId];
        require(!pending.fulfilled, "Already fulfilled");
        pending.fulfilled = true;
        
        CraftingRecipe storage recipe = recipes[pending.recipeId];
        _mintCraftingResult(pending.crafter, recipe, randomWords[0]);
    }
    
    function _mintCraftingResult(
        address crafter,
        CraftingRecipe storage recipe,
        uint256 random
    ) internal {
        uint256 outputTokenId;
        
        if (recipe.outputTokenId != 0) {
            // Детерміністичний вихід
            outputTokenId = recipe.outputTokenId;
        } else {
            // Random вихід у діапазоні [minOutputId, maxOutputId]
            outputTokenId = recipe.minOutputId + (random % (recipe.maxOutputId - recipe.minOutputId + 1));
        }
        
        // Мінтимо результат
        IGameItems(recipe.outputContract).mintCraftingResult(crafter, outputTokenId, 1);
        
        emit CraftingCompleted(crafter, recipe.recipeId, outputTokenId);
    }
    
    function _consumeInputMaterials(
        CraftingRecipe storage recipe,
        uint256[][] calldata inputTokenIds
    ) internal {
        for (uint i = 0; i < recipe.inputContracts.length; i++) {
            IERC1155 nft = IERC1155(recipe.inputContracts[i]);
            
            if (recipe.burnInputs) {
                // Спалюємо матеріали
                IERC1155Burnable(recipe.inputContracts[i]).burn(
                    msg.sender,
                    inputTokenIds[i][0],
                    recipe.inputAmounts[i]
                );
            } else {
                // Передаємо контракту (без спалювання)
                nft.safeTransferFrom(
                    msg.sender,
                    address(this),
                    inputTokenIds[i][0],
                    recipe.inputAmounts[i],
                    ""
                );
            }
        }
    }
}

Upgrade система (прокачка)

contract NFTUpgradeSystem {
    struct UpgradePath {
        uint256 itemTypeId;
        uint256 currentLevel;
        uint256 maxLevel;
        uint256[] materialCosts;  // матеріали для кожного рівня
        uint256[] tokenCosts;
        uint256 successRate;      // у basis points, 10000 = 100%
        bool destroyOnFail;       // спалити при неудачі?
    }
    
    // Upgrade з ризиком знищення (Korean-MMO стиль)
    function upgradeItem(
        uint256 tokenId,
        uint256 itemTypeId,
        uint256 targetLevel
    ) external returns (bool success) {
        UpgradePath storage path = upgradePaths[itemTypeId][targetLevel];
        
        // Забираємо матеріали
        _burnUpgradeMaterials(path);
        
        // Визначаємо успіх (off-chain random або VRF)
        // Для простоти — pseudo-random через block hash
        uint256 rand = uint256(keccak256(abi.encodePacked(
            blockhash(block.number - 1),
            msg.sender,
            tokenId,
            block.timestamp
        ))) % 10000;
        
        success = rand < path.successRate;
        
        if (success) {
            gameItems.setItemLevel(tokenId, targetLevel);
            emit UpgradeSuccess(msg.sender, tokenId, targetLevel);
        } else if (path.destroyOnFail) {
            gameItems.burn(msg.sender, itemTypeId, 1);
            emit UpgradeFailed(msg.sender, tokenId, targetLevel, true);
        } else {
            // Просто неудача без втрати предмета
            emit UpgradeFailed(msg.sender, tokenId, targetLevel, false);
        }
    }
}

Важливо: для upgrade з ризиком знищення VRF необхідний — гравець повинен бути впевнений, що казино не може маніпулювати шансом.

Crafting UI паттерни

Drag-and-drop слоти для матеріалів, preview результату до крафтинга, вероятності для random recipes, анімація крафтинга (прогрес бар або particle effect).

Розробка базової системи крафтинга (рецепти + fusion + детерміністичний вихід) — 3-4 тижні. З VRF random crafting і upgrade системою — 5-7 тижнів.