Разработка dApp (децентрализованного приложения)

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка dApp (децентрализованного приложения)
Сложная
от 2 недель до 3 месяцев
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1221
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    855
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1056
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    828

Разработка dApp (децентрализованного приложения)

dApp отличается от обычного веб-приложения не тем, что «использует блокчейн» — а тем, что критическая бизнес-логика исполняется на-чейн, и пользователь взаимодействует с ней напрямую через свой кошелёк, без посредника. Это принципиально другая архитектура: нет backend-сервера, который «владеет» данными пользователя, нет базы данных с балансами — только смарт-контракты и события. Всё остальное — проектные решения о том, сколько off-chain инфраструктуры вы готовы поддерживать.

Архитектурные решения на старте

Степень децентрализации

Первый вопрос — честный: что должно быть on-chain, а что нет? Каждый байт в смарт-контракте стоит газа. Хранить всё на-чейн — дорого и часто бессмысленно.

Полностью on-chain: логика + данные в контракте. Подходит для финансовых примитивов (AMM, lending, staking). Никакого бэкенда, работает через любой RPC.

Hybrid: логика on-chain, UI + indexing off-chain. 90% dApps. Контракт — source of truth для финансовых операций, off-chain backend — для быстрого поиска, нотификаций, аналитики.

Light dApp: смарт-контракт только для payments/ownership, основная функциональность — обычный веб-сервис. Часто правильный выбор для первой версии продукта.

Stack

Стандартный стек для 2024-2025: React 18 + TypeScript + Vite, Wagmi v2 + Viem для взаимодействия с блокчейном, RainbowKit или ConnectKit для wallet connection, TanStack Query для кэширования on-chain данных. Для SSR-требований — Next.js, но с осторожностью: server components + wagmi требуют аккуратной настройки.

State management: Zustand или Jotai хорошо подходят для dApp (меньше бойлерплейта, чем Redux, хорошо сочетаются с reactive wagmi hooks). Recoil — если проект уже использует его.

Wallet connection и authentication

Multi-wallet поддержка

Пользователи приходят с MetaMask, Coinbase Wallet, WalletConnect, Ledger, Safe. Wagmi v2 + WalletConnect v2 покрывает 95% кейсов из коробки. Кастомная интеграция нужна редко — только для корпоративных кошельков или специфичных use cases.

const config = createConfig({
    chains: [mainnet, polygon, arbitrum],
    transports: {
        [mainnet.id]: http(process.env.VITE_ALCHEMY_MAINNET_URL),
        [polygon.id]: http(process.env.VITE_ALCHEMY_POLYGON_URL),
        [arbitrum.id]: http(process.env.VITE_ALCHEMY_ARBITRUM_URL),
    },
    connectors: [
        injected(),
        coinbaseWallet({ appName: 'MyDApp' }),
        walletConnect({ projectId: WC_PROJECT_ID }),
    ],
});

SIWE (Sign-In with Ethereum)

Для dApps с off-chain компонентом (профили, настройки, уведомления) нужна аутентификация без пароля. SIWE (EIP-4361): пользователь подписывает текстовое сообщение с nonce, backend верифицирует подпись, выдаёт JWT. Это не транзакция — подпись бесплатна и мгновенна.

const message = new SiweMessage({
    domain: window.location.host,
    address: account.address,
    statement: 'Sign in with Ethereum to MyDApp.',
    uri: window.location.origin,
    version: '1',
    chainId: chain.id,
    nonce: await getNonce(), // с сервера, для replay protection
});

On-chain data fetching

Multicall и батчинг запросов

Naïve подход — отдельный RPC-вызов на каждый balanceOf, allowance, userInfo. При 20 токенах — 20 запросов, задержка ~2 секунды. Multicall3 (задеплоен на всех основных сетях по адресу 0xcA11bde05977b3631167028862bE2a173976CA11) позволяет упаковать N вызовов в один:

const results = await client.multicall({
    contracts: tokens.map(token => ({
        address: token.address,
        abi: erc20Abi,
        functionName: 'balanceOf',
        args: [userAddress],
    })),
});

Wagmi автоматически батчит useReadContracts через Multicall3. Но важно понимать лимиты: очень большие batch могут превысить gas limit ноды.

The Graph vs. собственный indexer

Для чтения исторических данных (события, транзакции, агрегаты) — нельзя полагаться на eth_getLogs с широким диапазоном блоков: ноды лимитируют запросы. Два варианта:

The Graph: GraphQL API поверх индексированных событий. Subgraph пишется на AssemblyScript, деплоится в Subgraph Studio. Хорошо для DeFi-данных (TVL, объёмы, позиции). Задержка индексирования — несколько блоков.

Alchemy/Moralis API: managed indexing без написания subgraph. Быстрее в старте, дороже в scale, меньше гибкости.

Собственный indexer: PostgreSQL + TypeScript сервис, слушающий события через WebSocket. Полный контроль, но поддержка инфраструктуры. Рекомендуется при специфичных требованиях к данным или высоких нагрузках.

Transaction UX

Транзакции — главный источник friction в dApps. Пользователь не должен угадывать, что происходит.

Состояния транзакции

Полный lifecycle: idle → signing (ждём подпись в кошельке) → pending (транзакция в mempool) → confirming (N из M confirmations) → success/error. Каждое состояние требует UI-обратной связи.

const { writeContractAsync, isPending } = useWriteContract();
const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({
    hash: txHash,
});

Gas estimation и EIP-1559

Wagmi/Viem использует EIP-1559 (maxFeePerGas + maxPriorityFeePerGas) по умолчанию на поддерживающих сетях. Для UX: показывать estimated fee в USD до подтверждения, используя eth_estimateGas + текущий gas price + ETH/USD oracle (Chainlink или CoinGecko API).

Слишком низкий gasLimit — транзакция упадёт с out-of-gas. Слишком высокий — пользователь видит пугающую цифру. Добавлять 20% буфер к estimated gas — стандартная практика.

Approve flow

ERC-20 требует approve перед transferFrom. Двухшаговый процесс (approve → действие) — источник confusion. Решения:

  • Permit (EIP-2612): одна подпись вместо approve-транзакции, если токен поддерживает
  • Безлимитный approve: один раз на контракт (UX хорошо, security плохо — не рекомендуем)
  • Точный approve: approve ровно на сумму текущей операции — правильно, но две транзакции каждый раз

Multichain и сеть

Chain switching

Пользователь может быть подключён к неправильному чейну. Автоматический запрос на смену:

const { switchChain } = useSwitchChain();

if (chain?.id !== targetChainId) {
    await switchChain({ chainId: targetChainId });
}

Для новых сетей (не в MetaMask по умолчанию) — wallet_addEthereumChain RPC метод для добавления.

RPC resilience

Единственный RPC — single point of failure. Для production: несколько провайдеров с fallback (Alchemy primary, Infura secondary, public RPC tertiary). Viem поддерживает fallback transport из коробки.

Безопасность frontend

  • Никакого приватного ключа на frontend — очевидно, но стоит написать явно
  • Верификация адресов контрактов из env-переменных, а не hardcode в коде
  • Content Security Policy против XSS — особенно критично, так как XSS в dApp может привести к кражe funds через фейковые транзакции
  • Проверка chainId в каждой транзакции — защита от replay attacks на другом чейне
  • ENS resolution с проверкой обратного lookup (address → ENS → address совпадает)

Ориентиры по срокам

MVP dApp (один чейн, базовые operations, wallet connect): 2-3 недели. Полноценный продукт с мультичейном, аналитикой, The Graph indexing и production-ready UX: 2-3 месяца.