Мой первый On-chain опыт на Base. The Wall Base: техническая архитектура социального мини-приложения на BaseAPP
18.12.25 Base запустила своё Mini App SDK, но я получил доступ к нему немного раньше еще на Beta-тестировании. Мне стало интересно: смогу ли я собрать миниаприложение, в котором каждое действие пользователя оставляет on-chain след. В статье описываю архитектуру, code-level решения, баги, инфраструктуру и все проблемы, которые пришлось пройти. Так появился The Wall Base — мини-приложение внутри Farcaster/BaseAPP
BaseAPP — Это web3 суперапп, эволюция кошелька Coinbase совмещающие в себе социальные сети, блокчейн, торговлю, платежи и мини-приложения

The Wall Base — состоит из:
социальной ленты постов;
минта NFT для каждого поста;
маркетплейс для торговли этими NFT;
prize-pool, который пополняется с каждого действия;
оффчейн-розыгрыш, выплачивающий пул случайному пользователю - владельцу поста.

Архитектура: как устроен The Wall Base
Стек:
Next.js 14 (App Router) — серверные компоненты, layout-маршруты;
TypeScript;
Tailwind;
Zustand для локального состояния;
viem и wagmi для on-chain взаимодействий.
Особенности App Router внутри Base App
Внутри Base App нельзя использовать:
полный SSR (часть окружения недоступна)
нестабильные fetch'и (некоторые origin блокируются)
системные навигации (всё должно быть «внутри mini-app sandbox»)
baseapp лоялен к vercel поэтому деплой я делал через него
Поэтому критично:
использовать
export const dynamic = "force-dynamic"там, где нужно обновлять UI при каждом запросе;избегать window-зависимых штук в серверных компонентах;
ограничить heavy API на серверных хэндлерах
/api/....
Бекенд-слой: /api, KV и off-chain данные
Посты живут off-chain — иначе мини-апп тормозил бы при каждом загрузке фида.
Хранилище:
KV (Vercel KV ) — основной вариант;
локальный json-файл в dev-режиме.
Часть данных:
Данные | Где хранятся | Почему |
|---|---|---|
Посты | KV | Быстро, почти бесплатные операции |
Реакции | KV | Низкий трафик, нет смысла писать on-chain |
История победителей | KV | Не критично быть on-chain |
Связь пост ↔ NFT | ForumNFT contract | Это самое ценное и должно быть on-chain |
Контракты: ForumNFT и Marketplace на Base mainnet
Все смарт-контракты проекта The Wall Base в финальной версии развернуты в сети Base mainnet.
Что такое Base
Base — это L2-сеть (rollup), построенная поверх Ethereum и разрабатываемая командой Coinbase.
Технически Base использует OP Stack, что даёт:
совместимость с EVM (Solidity, Hardhat, Foundry и т.д.);
низкие комиссии по сравнению с Ethereum mainnet;
быструю финализацию транзакций;
нативную интеграцию с экосистемой Coinbase и Base App.
Для мини-приложений Base подходит идеально: газ дешёвый, UX быстрый, а безопасность унаследована от Ethereum.
Несмотря на то, что продакшн-версия проекта работает в Base mainnet, вся разработка и отладка велись в Base Sepolia — тестовой сети Base.
Причины очевидны:
деплой контракта стоит реальные ETH;
каждая ошибка в логике = потеря денег;
тестовая сеть полностью повторяет поведение mainnet.
Для простого ERC-721 контракта деплой в Base mainnet в среднем обходится в 5–10 долларов, в зависимости от сложности и текущей загрузки сети.
Поэтому вся логика — от минта до prize pool — сначала полностью отрабатывалась в тестовой сети.
Важно понимать один момент, который часто путают новички. Смарт-контракт не «деплоится из IDE»
пишется локально (Solidity-файл);
компилируется локально (Hardhat);
отправляется в сеть через EVM-кошелёк.
Для деплоя нужен:
приватный ключ EVM-кошелька;
RPC-endpoint сети;
ETH на балансе (в тестовой или основной сети).
Фактически деплой — это обычная транзакция, в которой байткод контракта отправляется в сеть.
npx hardhat run scripts/deploy.js --network baseДля тестовой сети необходимо взять тестовые ETH - я тянул из крана https://www.alchemy.com/faucets/base-sepolia, но это для тех у кого есть активность в майнете. Для base sepolia я не нашел, альтернативный вариант - взять ETH в тестовой сети эфириум и перегнать их по мосту в base. Такие мосты существуют, но для новичков это тоже отдельный квест, если что спрашивайте в комментариях, я поищу конкретные мосты
После подтверждения транзакции:
контракт появляется в сети
получает адрес
начинает исполнять заложенную в него логику
Разделение on-chain и off-chain частей
В проекте чётко разделены два слоя:
On-chain
смарт-контракты (ForumNFT, Marketplace);
хранение денег;
ownership NFT;
prize pool.
Off-chain
фронтенд (Next.js);
хранение постов;
выбор победителя;
UI и UX;
взаимодействие с RPC.
Контракты не деплоятся вместе с фронтом — они живут отдельно и общаются с off-chain частью через RPC.
Переход с Base Sepolia на Base mainnet
Когда логика контрактов была полностью протестирована в Base Sepolia, переход в mainnet выглядел максимально просто:
Деплой контрактов в Base mainnet
Получение новых адресов контрактов
Замена конфигурации во фронтенде:
# было
NEXT_PUBLIC_BASE_RPC_URL=https://sepolia.base.org
NEXT_PUBLIC_NFT_CONTRACT_ADDRESS=0xTestAddress
# стало
NEXT_PUBLIC_BASE_RPC_URL=https://mainnet.base.org
NEXT_PUBLIC_NFT_CONTRACT_ADDRESS=0xMainnetAddressНикакой логики переписывать не пришлось — благодаря EVM-совместимости поведение контрактов в testnet и mainnet идентично, но трудно при переходе все же были, о н их я расскажу ниже
ForumNFT: кастомный ERC-721
Основные функции:
Минт за фиксированную цену
50% в
rewardPool, 50% вownerBalanceСвязи:
tokenToPost[tokenId]
Сервисные значения:
nextTokenIdMIN_REWARD_RESERVE = 0.0001 ether (оставляем для отправки транзакции)
adminSetNextTokenId
Admin-only, добавлена вручную:
function adminSetNextTokenId(uint256 value) external onlyOwnerЗачем она нужна?
Base mini-apps создают много временных тестовых постов, и я периодически «сжимал» состояние, делая полный burn всей коллекции. Тогда приходилось сбрасывать nextTokenId.
⚠ Но если сделать это без полного burn → коллизии:
один и тот же tokenId может уже существовать.
Marketplace: простая торговля NFT
листинг с указанием цены
покупка → комиссия
часть комиссии уходит в rewardPool
все покупки — обычные ETH-транзакции (Base → дешевле, чем в ETH mainnet)

Prize Pool: общая механика
Пул пополняется:
минты (50%) +
комиссии marketplace +
ownerBalance (если вручную отправляю)
прямые переводы на контрактРезерв 0.0001 ETH всегда остаётся нетронутым, иначе prizePool может «обнулиться» и не будет хватать на курс ETH запросы.
Почему розыгрыш оффчейн
Потому что Base Mini Apps:
не предполагают генерацию on-chain randomness;
нет встроенного безопасного VRF;
нельзя заставить юзера подтверждать chainlink VRF callback.
Реализация:
/api/reward/drawвыбирает случайный пост (через PRNG + фильтр used posts).Создаёт транзакцию
payPrize(winner, tokenId, amount).Записывает победителя в KV.
Интеграция с Farcaster Mini App SDK
Использую:
sdk.actions.openUrl()— для открытия профиля юзера в Base App;sdk.actions.openPage()— для переходов внутрь mini-app;sdk.ready()— обязательное условие перед рендером UI.
Особые требования Mini App:
mini-app не может делать навигацию по window.location;
ссылки должны быть whitelisted в манифесте;
base.app и farcaster.xyz работают — остальные нет.
RPC: почему ничего не работает в маинет
Это был один из самых неприятных технических моментов, я долго не мог понять почему в маркетплейс не подгружаются имеющиеся NFT и не обновляется призовой пул. Проблема заключался в пропускной способности публичных RPC
Я начал с публичных RPC:
Infura / Alchemy shared endpoints
Проблемы:
периодические timeouts (4–7 сек) при чтении состояния;
нестабильные ответы на viem/wagmi вызовы;
иногда возвращался
execution revertedпри нормальных функциях;eth_callмог работать, аeth_sendTransaction— падал;Base App (мобильное окружение) имеет свои rate-limits.
Внутри мини-приложения это критично — фид и marketplace должны отвечать мгновенно.
Решение: перейти на приватные RPC от Coinbase Developer Platform
Обычно, такие RPC стоят денег, но на Coinbase Developer Platform я взял их бесплатно, в добавок мне дали 500 USDC на услуги компании и на возврат комиссий сети для пользователей моего приложения
Я завёл приватный endpoint:
https://base-mainnet.g.alchemy.com/v2/<private_key>и использовал его в переменной:
NEXT_PUBLIC_BASE_RPC_URL=<private RPC>Результат:
время ответа упало до 90–120 мс;
ни одного пропущенного
eth_call;стабильный work в мобильных окружениях;
marketplace начал грузиться без ошибок;
prizePool на UI стал обновляться стабильно.
Mini-apps очень чувствительны к задержкам, и разница между публичным и приватным RPC ощущается очень сильно
Админ-панель: технически важные детали
В админке есть:
просмотр ownerBalance
управление комиссией
ручной розыгрыш пула
кнопка сброса tokenId
скрытие постов - для модерации
пометка звездных постов - для пуша звездных пользователей блокчейна
Безопасность:
все админ-операции проверяются по адресу
ADMIN_ADDRESSfront блокирует доступ, но главный контроль — on-chain проверка
onlyOwner
Манифест mini-app и ассеты
Файл: public/.well-known/farcaster.json
Свойства:
{
"name": "The Wall Base",
"description": "Farcaster mini-app: NFT posts, marketplace, prize pool",
"iconUrl": "/200_00000.png",
"splashUrl": "/1024_00000.png",
"webhookUrl": null,
"requestedPermissions": [],
"developer": "base.app/<username>"
}
Важно: Стадия разработки должна использовать noindex=true, иначе кастомный манифест будет кэшироваться у клиента.
Частые проблемы и решения
1. wagmi + mini-app окружение
Нельзя полагаться на window.ethereum. Используется кастомный Base App connector.
2. BigInt в React state
Mini-app WebView может падать, если BigInt попадает в JSON.
Решение — сериализация via string.
3. ETH → USD курс
CMC часто блокирует частые запросы. Решение: кеширование на 30 минут.
Деплой: контракты и фронт
Контракты (Hardhat)
npx hardhat run scripts/deploy.js --network base
npx hardhat verify --network base <ForumNFT> "<deployer>"Фронт (Vercel)
root:
/miniappbuild:
npm run buildenv: приватный RPC + адреса контрактов
Заключение
The Wall Base стал для меня экспериментом, который неожиданно вышел в полноценный продукт:
социальная сеть → но каждый пост — NFT;
marketplace → но встроенный в мини-апп;
prize-pool → полностью живёт on-chain;
интеграция Base App → работает как мобильное нативное приложение.
Главный вывод: Base Mini-apps открывают огромную нишу для гибридных dApps, если вас заинтересовала разработка на baseapp воспользуйтесь ссылками ниже
Приложение BaseAPP (пока доступно по инвайту, но скоро это станет не обязательно)
Документация
The Wall Base