Разработка лендинга NFT-минта
Лендинг минта — это точка максимального напряжения в жизни NFT-проекта. 10 минут между открытием минта и soldout: тысячи одновременных транзакций, MetaMask у половины пользователей не отвечает, галерея не загрузилась, таймер показывает нули — а кнопки нет. Такие лендинги сжигают доверие и деньги одновременно.
Технически хороший лендинг минта — это не красивый дизайн. Это правильная обработка состояний кошелька, корректный gas estimate, обработка очереди транзакций и graceful degradation при RPC перегрузке.
Критичные технические компоненты
Таймер и синхронизация с блокчейном
Таймер должен отсчитывать время до конкретного блока или unix timestamp из контракта, а не хардкоженную дату. Иначе: маркетинг объявляет минт «в 18:00», разработчик деплоит контракт с startTime на 5 минут позже из-за задержки деплоя — кнопка минта неактивна ещё 5 минут после «старта».
Корректная реализация: читаем mintStartTime() из контракта через wagmi useReadContract, высчитываем разницу с Date.now(). Таймер на клиенте, источник правды — контракт.
Обработка состояний минта
Конечный автомат состояний кнопки: disconnected → wrong-network → not-started → allowlist-only (если в WL) → ready → pending → success → sold-out. Каждое состояние — отдельный UI. Кнопка «Mint» без обработки pending состояния приводит к двойным транзакциям: пользователь думает что нажал зря, жмёт снова, обе проходят.
Allowlist проверка: если контракт имеет публичный и WL-этап, клиент должен проверить Merkle proof до показа кнопки. Локально — сгенерировать proof для подключённого адреса из tree, вызвать isWhitelisted(address, proof) или MerkleProof.verify() view-функцию контракта. Это off-chain, газа не стоит.
Gas estimation и динамический maxFeePerGas
Фиксированный gasLimit в транзакции — ошибка. Если контракт добавил логику между тестом и деплоем — газ изменился. Используем estimateGas через viem перед отправкой + буфер 20%.
Для EIP-1559 транзакций: maxFeePerGas должен учитывать текущий baseFee. При высокой нагрузке в момент минта baseFee может вырасти в 5x. Кнопка «Mint» с maxFeePerGas из момента загрузки страницы, но отправленная через 30 секунд, может ревертиться с max fee per gas less than block base fee. Решение: пересчитывать maxFeePerGas непосредственно перед отправкой транзакции.
RPC fallback при перегрузке
В момент хайпового минта публичные Alchemy/Infura endpoint'ы перегружаются. Транзакции не отправляются, eth_call не отвечает. Критически важно иметь несколько RPC endpoint'ов с fallback через wagmi fallbackTransport:
const transport = fallback([
http(process.env.ALCHEMY_RPC),
http(process.env.INFURA_RPC),
http('https://eth.llamarpc.com'),
])
При failure одного — автоматически переключается на следующий.
Галерея коллекции
Lazy loading с intersection observer: загружаем только видимые изображения. Для 10k коллекции — виртуализация списка через @tanstack/react-virtual. IPFS изображения через Pinata dedicated gateway (в 10x быстрее публичных gateway). Fallback при недоступности IPFS — загрушка-плейсхолдер, не сломанный img тег.
Стек
Next.js 14 (App Router) + wagmi v2 + viem + RainbowKit для wallet connect UI. Tailwind CSS для стилей. Анимации через Framer Motion — reveal коллекции, countdown таймер, success confetti после минта.
Процесс и сроки
Дизайн (1 день): Figma макет с компонентами, мобильная версия.
Разработка (2–3 дня): галерея, таймер, mint-компонент со всеми состояниями, wallet integration.
Интеграция контракта (0.5 дня): подключение ABI, тестирование на testnet.
QA (0.5 дня): тест на разных кошельках (MetaMask, Coinbase, Rainbow), мобильные браузеры, все состояния минта.
Итого: 3–5 дней. Стоимость рассчитывается индивидуально.







