Реализация NFT-маркетплейса на сайте

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация NFT-маркетплейса на сайте
Сложная
от 2 недель до 3 месяцев
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Реализация NFT-маркетплейса на сайте

NFT-маркетплейс — платформа для выпуска, выставления на продажу, покупки и аукциона NFT. Полноценный маркетплейс включает смарт-контракты на блокчейне, фронтенд для взаимодействия с ними и бэкенд для индексирования данных.

Компоненты маркетплейса

Frontend (Next.js + Wagmi)
    │
    ├── Смарт-контракты (Solidity)
    │     ├── NFT Collection (ERC-721/ERC-1155)
    │     ├── Marketplace Contract (listing, buy, auction)
    │     └── Royalty (EIP-2981)
    │
    ├── Indexer (The Graph / собственный)
    │     └── Читает события из блокчейна → PostgreSQL
    │
    └── Backend API
          ├── Метаданные NFT (IPFS/Arweave)
          └── Аналитика, поиск, фильтры

Смарт-контракт: Marketplace

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

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract NFTMarketplace is ReentrancyGuard, Ownable {
    uint256 public platformFee = 250;  // 2.5% в basis points
    uint256 public constant FEE_DENOMINATOR = 10000;

    struct Listing {
        address seller;
        address nftContract;
        uint256 tokenId;
        uint256 price;
        bool active;
    }

    mapping(bytes32 => Listing) public listings;
    mapping(address => uint256) public proceeds;

    event NFTListed(
        bytes32 indexed listingId,
        address indexed seller,
        address indexed nftContract,
        uint256 tokenId,
        uint256 price
    );

    event NFTSold(
        bytes32 indexed listingId,
        address indexed buyer,
        uint256 price
    );

    function listNFT(
        address nftContract,
        uint256 tokenId,
        uint256 price
    ) external returns (bytes32 listingId) {
        require(price > 0, "Price must be > 0");
        IERC721 nft = IERC721(nftContract);
        require(nft.ownerOf(tokenId) == msg.sender, "Not owner");
        require(
            nft.isApprovedForAll(msg.sender, address(this)) ||
            nft.getApproved(tokenId) == address(this),
            "Marketplace not approved"
        );

        listingId = keccak256(abi.encodePacked(nftContract, tokenId, msg.sender, block.timestamp));

        listings[listingId] = Listing({
            seller: msg.sender,
            nftContract: nftContract,
            tokenId: tokenId,
            price: price,
            active: true
        });

        emit NFTListed(listingId, msg.sender, nftContract, tokenId, price);
    }

    function buyNFT(bytes32 listingId) external payable nonReentrant {
        Listing storage listing = listings[listingId];
        require(listing.active, "Listing not active");
        require(msg.value >= listing.price, "Insufficient payment");

        listing.active = false;

        // Комиссия платформы
        uint256 fee = (listing.price * platformFee) / FEE_DENOMINATOR;
        uint256 sellerAmount = listing.price - fee;

        // Роялти (EIP-2981)
        (address royaltyReceiver, uint256 royaltyAmount) = _getRoyalty(
            listing.nftContract, listing.tokenId, listing.price
        );

        if (royaltyAmount > 0 && royaltyAmount < sellerAmount) {
            sellerAmount -= royaltyAmount;
            proceeds[royaltyReceiver] += royaltyAmount;
        }

        proceeds[listing.seller] += sellerAmount;
        proceeds[owner()] += fee;

        // Перевод NFT покупателю
        IERC721(listing.nftContract).safeTransferFrom(
            listing.seller, msg.sender, listing.tokenId
        );

        // Возврат переплаты
        if (msg.value > listing.price) {
            payable(msg.sender).transfer(msg.value - listing.price);
        }

        emit NFTSold(listingId, msg.sender, listing.price);
    }

    function withdrawProceeds() external nonReentrant {
        uint256 amount = proceeds[msg.sender];
        require(amount > 0, "No proceeds");
        proceeds[msg.sender] = 0;
        payable(msg.sender).transfer(amount);
    }
}

Frontend: листинг и покупка

import { useWriteContract, useReadContract, useAccount } from 'wagmi';
import { parseEther } from 'viem';

function BuyNFT({ listingId, price }) {
  const { address } = useAccount();
  const { writeContractAsync, isPending } = useWriteContract();

  const { data: listing } = useReadContract({
    address: MARKETPLACE_ADDRESS,
    abi: marketplaceAbi,
    functionName: 'listings',
    args: [listingId]
  });

  const handleBuy = async () => {
    await writeContractAsync({
      address: MARKETPLACE_ADDRESS,
      abi: marketplaceAbi,
      functionName: 'buyNFT',
      args: [listingId],
      value: price
    });
  };

  return (
    <button onClick={handleBuy} disabled={isPending || !address}>
      {isPending ? 'Обработка...' : `Купить за ${formatEther(price)} ETH`}
    </button>
  );
}

Метаданные NFT (IPFS)

import { NFTStorage } from 'nft.storage';

const client = new NFTStorage({ token: process.env.NFT_STORAGE_KEY });

async function uploadNFTMetadata(
  file: File,
  name: string,
  description: string,
  attributes: Array<{ trait_type: string; value: string }>
): Promise<string> {
  const metadata = await client.store({
    name,
    description,
    image: file,
    attributes
  });

  // Возвращает IPFS URI: ipfs://bafyrei...
  return metadata.url;
}

Индексирование через The Graph

// subgraph.yaml
dataSources:
  - kind: ethereum
    name: NFTMarketplace
    source:
      address: "0xYourMarketplaceContract"
      abi: NFTMarketplace
    mapping:
      eventHandlers:
        - event: NFTListed(indexed bytes32,indexed address,indexed address,uint256,uint256)
          handler: handleNFTListed
        - event: NFTSold(indexed bytes32,indexed address,uint256)
          handler: handleNFTSold
// mapping.ts (AssemblyScript)
export function handleNFTListed(event: NFTListed): void {
  let listing = new Listing(event.params.listingId.toHex());
  listing.seller = event.params.seller;
  listing.nftContract = event.params.nftContract;
  listing.tokenId = event.params.tokenId;
  listing.price = event.params.price;
  listing.active = true;
  listing.createdAt = event.block.timestamp;
  listing.save();
}

Сроки реализации

  • Смарт-контракты (листинг + продажа) + тесты — 2–3 недели
  • Frontend с Wagmi + листинг/покупка/выставление — 2–3 недели
  • Индексер (The Graph) + поиск/фильтры — 1–2 недели
  • Полный маркетплейс с аукционом и royalties — 2–3 месяца