Реализация маркетплейса внутриигровых предметов в мобильной GameFi-игре
Разработка NFT-маркетплейса внутри мобильной игры — одна из самых сложных задач, с которой мы сталкиваемся в GameFi-проектах. По нашим данным, до 70% пользователей бросают маркетплейсы из-за высоких газовых комиссий и сложного онбординга. Здесь сталкиваются два мира: привычный мобильный UX (быстро, интуитивно, без seed-фраз) и блокчейн-реальность (gas fees, время подтверждения транзакций, ownership через кошелёк). Если не решить это противоречие — маркетплейс просто не будут использовать. Мы гарантируем решение за счёт опыта в интеграции Account Abstraction и off-chain листингов. Если вы столкнулись с падением пользователей или высокими газовыми затратами — свяжитесь с нами, мы поможем.
Почему off-chain листинги критичны для мобильного GameFi?
Полностью on-chain маркетплейс (как OpenSea v1) — каждый листинг это транзакция. На мобильных устройствах это нецелесообразно: пользователь не будет платить $0.50–5 газа за каждое выставление предмета на продажу. Off-chain листинги работают в 10 раз быстрее и экономят до 90% на газе.
Правильная архитектура для GameFi-мобайла — off-chain листинги с on-chain расчётами:
- Продавец подписывает листинг оффчейн (
signTypedData/ EIP-712) — транзакции нет, газа нет - Листинг хранится в базе данных приложения
- Покупатель нажимает «Купить» — только в этот момент происходит on-chain транзакция
- Смарт-контракт верифицирует подпись продавца, переводит NFT покупателю и оплату продавцу атомарно
struct Listing { address seller; address nftContract; uint256 tokenId; address paymentToken; uint256 price; uint256 expiry; uint256 nonce; } bytes32 public constant LISTING_TYPEHASH = keccak256( "Listing(address seller,address nftContract,uint256 tokenId,address paymentToken,uint256 price,uint256 expiry,uint256 nonce)" ); function buyItem(Listing calldata listing, bytes calldata signature) external { require(block.timestamp < listing.expiry, "Listing expired"); require(!usedNonces[listing.seller][listing.nonce], "Nonce used"); bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(LISTING_TYPEHASH, listing))); require(ECDSA.recover(digest, signature) == listing.seller, "Invalid signature"); usedNonces[listing.seller][listing.nonce] = true; IERC20(listing.paymentToken).transferFrom(msg.sender, listing.seller, listing.price); IERC721(listing.nftContract).safeTransferFrom(listing.seller, msg.sender, listing.tokenId); } Этот подход используют Seaport (OpenSea v2) и Blur — проверенная схема.
Как обеспечить бесшовный UX покупки NFT на мобильном?
Главная проблема — как пользователь подписывает транзакцию покупки без seed-фразы в приложении. Рассмотрим три варианта:
| Метод | UX | Безопасность | Сложность реализации |
|---|---|---|---|
| Account Abstraction (Privy/Dynamic) | Биометрия, без газа | Высокая (smart account) | Средняя |
| WalletConnect (MetaMask/Phantom) | Deep Link, уход из приложения | Высокая (внешний кошелёк) | Низкая |
| Кастодиальный кошелёк (Fireblocks MPC) | Встроенный, максимально простой | Средняя (ключи у сервера) | Средняя |
Для GameFi с миллионной аудиторией мы рекомендуем Account Abstraction. Пользователь входит через Google/Apple — получает smart account автоматически. Paymaster спонсирует газ, экономия до 90% на комиссиях. Наша команда сертифицированных инженеров имеет опыт внедрения Privy и Dynamic в игровых проектах.
Что входит в работу
- Смарт-контракт маркетплейса с аудитом
- Бэкенд: индексирование метаданных, листинги, полнотекстовый поиск
- Мобильный клиент: грид предметов, карточка, поток покупки
- Интеграция кошелька (WalletConnect или Account Abstraction)
- Фильтры, сортировка, история сделок
- Документация по API и смарт-контракту
- Тестовая документация и поддержка при запуске
Как работает off-chain листинг с точки зрения пользователя?
Пользователь заходит в маркетплейс, выбирает предмет и нажимает «Купить». Система проверяет подпись листинга, которую продавец создал заранее off-chain. Транзакция в блокчейне происходит только в этот момент — пользователь подписывает её через свой smart account (биометрия). Весь процесс занимает менее 10 секунд, а газ спонсируется Paymaster.
Процесс покупки: пошагово
Каждый NFT-предмет — это tokenId + метаданные с tokenURI на IPFS или centralised CDN. Мы индексируем метаданные в базу данных и отдаём через REST API — мобильный клиент никогда не обращается к IPFS напрямую. Изображения предметов доставляются через CDN (CloudFront / Cloudflare), с кэшированием на клиенте через Kingfisher (iOS) или Coil (Android). Lazy loading в списке — LazyColumn с AsyncImage в Compose, LazyVGrid в SwiftUI.
struct MarketplaceGridView: View { @StateObject var viewModel: MarketplaceViewModel let columns = [GridItem(.adaptive(minimum: 160), spacing: 12)] var body: some View { ScrollView { LazyVGrid(columns: columns, spacing: 12) { ForEach(viewModel.items) { item in NFTItemCard(item: item) .onAppear { if item == viewModel.items.last { viewModel.loadNextPage() } } } } .padding() } } } Типичные ошибки при разработке
- Загрузка метаданных напрямую с IPFS (медленно, нестабильно) — правильное решение: бэкенд-индексирование.
- Использование on-chain листингов (дорогой газ) — решение: off-chain подписи EIP-712.
- Отсутствие проверки nonce и срока действия листинга (replay attack) — в коде выше это учтено.
Фильтрация и поиск
Фильтры: редкость (Rare/Epic/Legendary), тип предмета (оружие/броня/питомец), ценовой диапазон, актив оплаты. Сортировка: по цене, по дате листинга, по редкости. Полнотекстовый поиск по имени предмета — через PostgreSQL tsvector или Elasticsearch на бэкенде. Атрибуты NFT-предметов индексируются в реляционную таблицу при минте — не парсятся из IPFS JSON при каждом запросе.
Роялти и модерация
При каждой P2P-продаже на вторичном рынке — автоматическое отчисление роялти (2–5%) в кошелёк студии. ERC-2981 (NFT Royalty Standard) задаёт royaltyInfo(tokenId, salePrice) — смарт-контракт маркетплейса вызывает это перед расчётом и удерживает комиссию.
Система жалоб на подозрительные листинги (чит-предметы, дубликаты). Административный endpoint POST /listings/{id}/delist — удаляет листинг из базы. On-chain ничего не меняется (транзакции не было), предмет просто перестаёт отображаться. Блокировка краденых токенов (если аккаунт взломан) — blacklist на уровне смарт-контракта: blockedTokens[tokenId] = true с проверкой в buyItem.
Сроки и стоимость
| Этап | Срок |
|---|---|
| Смарт-контракт маркетплейса + аудит | 2 недели |
| Бэкенд: индексирование, листинги, поиск | 2 недели |
| Мобильный клиент: грид, карточка, покупка | 2–3 недели |
| Кошелёк (WalletConnect или Account Abstraction) | 1 неделя |
| Фильтры, сортировка, история сделок | 1 неделя |
Итого: 8–10 недель. Стоимость рассчитывается индивидуально после анализа требований. Получите консультацию по вашему проекту прямо сейчас — свяжитесь с нами для бесплатной оценки.







