Реалізація маркетплейсу внутрішньоігрових предметів у мобільній 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 тижнів. Вартість розраховується індивідуально після аналізу вимог. Отримайте консультацію щодо вашого проєкту прямо зараз — зв'яжіться з нами для оцінки.







