При продажу NFT через мобільний додаток користувач стикається з двома обов'язковими транзакціями: approve та лістинг. Кожна вимагає підтвердження та витрати газу. Ми у своїй практиці часто бачимо, як неправильний вибір між approve та setApprovalForAll призводить до зайвих витрат або втрати довіри. Розберемо, як реалізувати цей процес без помилок.
Як вибрати між approve та setApprovalForAll?
setApprovalForAll(marketplaceAddress, true) — один дозвіл для всіх токенів колекції. Користувач робить це один раз, потім може лістити будь-які NFT з цієї колекції без повторного approve. approve(marketplaceAddress, tokenId) — дозвіл для конкретного токена. Безпечніше, але кожен лістинг вимагає окремої транзакції.
| Критерій | setApprovalForAll | approve |
|---|---|---|
| Кількість транзакцій на перший лістинг | 1 (approve) + 1 (list) = 2 | 1 (approve) + 1 (list) = 2 |
| Кількість транзакцій на наступний лістинг | 1 (list) | 2 (approve + list) |
| Газові витрати на 5 лістингів | 2 + 4*1 = 6 транзакцій | 5*2 = 10 транзакцій |
| Безпека | Нижча (ризик для всієї колекції) | Вища (тільки один токен) |
| UX | Краще — менше підтверджень | Гірше — кожного разу approve |
Рекомендований UX: при першому лістингу з колекції — пропонувати setApprovalForAll з поясненням «Дозвольте один раз для всієї колекції, щоб не платити газ при кожному продажу». Користувач повинен розуміти наслідки. Для rare tokens (1/1) можна використовувати approve. ERC721 — стандарт, з яким ми працюємо.
// iOS — перевірка схвалення перед лістингом func checkApproval(nftContract: EthereumAddress, owner: EthereumAddress) async -> Bool { let erc721 = ERC721(web3: web3, provider: web3.provider, address: nftContract) return (try? await erc721.getApproved(tokenId: tokenId) == marketplaceAddress) ?? (try? await erc721.isApprovedForAll(owner: owner, operator: marketplaceAddress)) ?? false } Як оптимізувати газові витрати при approve?
На Ethereum кожна транзакція коштує дорого, на Polygon — мінімальні комісії. Якщо ваш додаток працює на кількох мережах, дайте користувачу вибрати мережу з низькою комісією. Використовуйте setApprovalForAll для економії газу на наступних лістингах — це скорочує кількість транзакцій у 2 рази. setApprovalForAll краще approve: для 5 лістингів потрібно всього 6 транзакцій замість 10, що економить 40% газу.
| Операція | Ethereum (gwei 50) | Polygon (gwei 100) |
|---|---|---|
| approve | висока комісія | мінімальна комісія |
| list | висока комісія | мінімальна комісія |
| updateListing | висока комісія | мінімальна комісія |
| cancelListing | висока комісія | мінімальна комісія |
Форма лістингу та розбивка комісій
Мінімум полів: ціна (в ETH або ERC-20 токені), опціональний дедлайн лістингу. Показуй прямо у формі розрахункову суму, яку отримає продавець з урахуванням комісій: netAmount = price * (1 - platformFee - royalty).
// Android — розрахунок чистої суми при лістингу NFT для Kotlin val grossPrice: BigDecimal, val platformFeePercent: BigDecimal, val royaltyPercent: BigDecimal, val platformFeeAmount get() = grossPrice * platformFeePercent / BigDecimal(100) val royaltyAmount get() = grossPrice * royaltyPercent / BigDecimal(100) val sellerReceives get() = grossPrice - platformFeeAmount - royaltyAmount Роялті береться з ERC2981.royaltyInfo(tokenId, price). Показуйте рядок «Роялті творцю: X%» — це важливо для прозорості. Відсутність цієї інформації знижує довіру користувачів.
Чому важливо показувати чисту суму продавцю?
Користувач бачить 1 ETH, але після комісій отримує 0.85 ETH. Якщо не показати розбивку, він буде розчарований при отриманні. Попередній показ комісій збільшує завершення транзакцій на 20%.
Flow створення лістингу з чекпоїнтами
- Перевірити схвалення → якщо ні, відправити
approve/setApprovalForAll. Показувати модальне вікно з поясненням. - Дочекатися підтвердження approve — індикатор прогресу з анімацією блоку.
- Відправити
listItem(nftAddress, tokenId, price, deadline)— знову чекати підтвердження. - Після підтвердження — NFT з'являється в каталозі.
Кожен крок з прогрес-індикатором. Якщо користувач закрив додаток після кроку 1 — при наступному відкритті перевірити схвалення (вже видане) і запропонувати продовжити з кроку 3. Така відмовостійкість — обов'язкова вимога для production-додатків.
Типові помилки при approve:
- Користувач не дочекався підтвердження approve і відправив list — транзакція провалиться.
- Недостатній баланс ETH для газу — запропонуйте попередньо поповнити гаманець.
- Approve на неправильну адресу маркетплейсу — завжди перевіряйте адресу в UI.
Зміна ціни та зняття з продажу
updateListing(nftAddress, tokenId, newPrice) — одна транзакція без повторного approve. cancelListing(nftAddress, tokenId) — зняття лістингу. Після підтвердження — NFT зникає з каталогу. Важно: відображати кнопку «Зняти з продажу» тільки тоді, коли лістинг дійсно активний (перевірка on-chain або через індексатор). Якщо перевіряти тільки локально, можливі race conditions.
Що входить у реалізацію
Ми маємо понад 10 років досвіду в mobile blockchain integrations. Ми реалізуємо весь цикл продажу NFT у мобільному додатку:
- Розробка UI форми лістингу NFT на iOS з розбивкою комісій.
- Інтеграція смарт-контрактів ERC721/ERC1155 та ERC2981.
- Обробка push-сповіщень про статус транзакції (через APNs/FCM).
- Тестування на реальних пристроях та симуляторах.
- Підготовка метаданих для App Store та Google Play (включаючи опис App Store Review Guidelines Section 4.2).
Процес оцінки та роботи
- Збір даних: ваші вимоги та поточний стек.
- Аудит та аналіз: перевірка смарт-контрактів, UX.
- Проектування: архітектура інтеграції.
- Оцінка: точний обсяг робіт та строки.
- Розробка: ітеративна з демо на кожному етапі.
- Тестування: unit, integration, приймальне на реальних пристроях.
- Запуск: публікація в App Store/Google Play.
Орієнтири за строками
Від 3 до 5 робочих днів. Оцінимо ваш проект за 1 день. Отримайте консультацію по вашому проекту — ми гарантуємо прозорість та дотримання строків. Зв'яжіться з нами для обговорення деталей.







