Як ми створюємо децентралізовані чати з XMTP та Waku

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1305 послуг
Як ми створюємо децентралізовані чати з XMTP та Waku
Складний
від 1 тижня до 3 місяців
Часті запитання

Напрямки блокчейн-розробки

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1357
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1250
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    956
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1188
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    646
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    929

Ми стикаємося з типовою ситуацією: клієнт хоче захистити переписку, але водночас зберегти незмінну історію для аудиту. Зберігати кожне повідомлення в блокчейні Ethereum mainnet коштує від $2 до $10 — це дорогий публічний реєстр, не придатний для звичайного чату. Наш підхід — гібридна система, де блокчейн використовується лише там, де він дає переваги: аутентифікація, токен-гейтинг, мікроплатежі. Наприклад, перевірка володіння NFT при вступі в чат виконується за один RPC-запит (вартість <$0.001), а реєстрація через гаманець займає секунду. Такий підхід економить до 90% газових комісій порівняно з повним on-chain зберіганням. Ми комбінуємо E2E-шифрування (X3DH, як у Signal) та децентралізоване зберігання ключів на блокчейні. Оцінимо ваш проєкт — пишіть.

Як XMTP забезпечує E2E-шифрування?

XMTP (Extensible Message Transport Protocol) використовує протокол X3DH (Extended Triple Diffie-Hellman) для встановлення спільного секрету між відправником та отримувачем. Кожне повідомлення шифрується на клієнті та розшифровується лише отримувачем. Групові чати використовують MLS (Messaging Layer Security, RFC 9420) з forward secrecy та post-compromise security. Signal Protocol використовує аналогічну схему, але XMTP адаптує її для Ethereum-адрес. В результаті навіть оператор XMTP-ноди не може прочитати вміст повідомлень — лише метадані (від кого, кому, коли).

Проблеми, які ми вирішуємо

  1. Висока вартість on-chain зберігання: одна транзакція з текстом на Ethereum може коштувати $0.5-2, а для частого обміну це мільйони доларів на рік.
  2. Конфіденційність vs незмінність: потрібна гарантія, що повідомлення не змінять, але без публічного оприлюднення.
  3. Контроль доступу: обмеження чату для власників певних токенів без централізованого сервера.
  4. Мікроплатежі: автоматична оплата за кожне повідомлення або чайові без посередників.

Як ми це робимо: технічні деталі

Простір рішень: від on-chain до гібрида

Повністю on-chain має сенс лише для специфічних сценаріїв:

  • Governance proposals (Snapshot, Tally) — незмінність важлива.
  • Dispute resolution — докази повинні бути захищені від підробки.
  • Critical announcements для DAO — доказова публічність.

Для цих випадків ми використовуємо події Ethereum (event MessagePosted(address indexed sender, bytes32 indexed channelId, string content)). Calldata для зберігання тексту дешевше storage: на Ethereum mainnet 1KB calldata ≈ 16000 gas ≈ $0.5-2. На Arbitrum або Base — в 10-50 разів дешевше.

P2P з on-chain identity: XMTP

XMTP — production-ready протокол, де-факто стандарт для Web3 повідомлень. Використовується в Coinbase Wallet, Converse, багатьох dApps. Архітектура:

  • Identity на основі Ethereum адреси.
  • Повідомлення шифруються end-to-end через X3DH.
  • Транспорт — децентралізована P2P мережа XMTP nodes.
  • On-chain: лише ключова інформація при реєстрації.
import { Client } from '@xmtp/xmtp-js';
import { ethers } from 'ethers';

const signer = await provider.getSigner();
const xmtp = await Client.create(signer, { env: 'production' });

const conversation = await xmtp.conversations.newConversation(
  '0xRecipientAddress'
);

await conversation.send('Привіт з dApp!');

for await (const message of await conversation.streamMessages()) {
  console.log(`${message.senderAddress}: ${message.content}`);
}

XMTP підтримує structured content types: транзакційні сповіщення, NFT attachments, read receipts. Це особливо важливо для DeFi контексту: «Надіслав тобі 100 USDC» з embedded transaction preview.

Групові чати: XMTP MLS

XMTP v3 додав групи на базі MLS — криптографічний протокол для групового шифрування з forward secrecy та post-compromise security.

import { Client } from '@xmtp/xmtp-js';

const group = await xmtp.conversations.newGroup([
  '0xAddress1',
  '0xAddress2',
  '0xAddress3'
]);

await group.send('Всім привіт!');

await group.addMembers(['0xNewMember']);
await group.removeMembers(['0xOldMember']);

Чому блокчейн не підходить для зберігання повідомлень?

Основна цінність блокчейну — децентралізована аутентифікація та керування доступом. Реєстрація через підпис гаманця (EIP-4361) дає криптографічний доказ володіння адресою без паролів. Токен-гейтинг обмежує доступ на основі on-chain умов. Платіжні канали (Superfluid) автоматизують мікроплатежі. Використовуючи блокчейн лише для identity, ми знижуємо витрати на 80-95% і отримуємо масштабованість.

Порівняння XMTP та Waku

Характеристика XMTP Waku
Identity Ethereum-адреса (обов'язково) Опціонально, можна будь-який
Транспорт P2P мережа XMTP-нод P2P (libp2p, gossipsub)
Шифрування X3DH + MLS Опціонально (на рівні застосунку)
Зберігання історії Зовнішнє (Ceramic, Arweave) Waku Store (обмежений TTL)
Token-gating Через застосунок Через зовнішній шар
Мікроплатежі Superfluid Зовнішні рішення

Як інтегрувати XMTP за 4 кроки

  1. Налаштування гаманця: Підключіть Ethereum-гаманець (MetaMask, WalletConnect). Отримайте signer через ethers.js або viem.
  2. Створення клієнта XMTP: Ініціалізуйте Client.create(signer, { env: 'production' }). Генеруються ключі та реєструється identity (потрібна одна on-chain транзакція).
  3. Створення бесіди: Викличте client.conversations.newConversation(address) для 1-on-1 або newGroup(addresses) для груп. Бесіда готова до обміну.
  4. Відправлення та підписка: Використовуйте conversation.send(text) та streamMessages() для отримання в реальному часі. Все E2E-зашифровано.

Безсерверний token-gate через XMTP

У XMTP token-gating можна реалізувати на стороні клієнта: при вступі в групу користувач підписує attestation свого on-chain статусу. Існуючі учасники верифікують підпис через Ethereum provider. Для складніших сценаріїв — Lit Protocol, де лише гаманець з потрібним NFT може отримати ключ розшифрування каналу.

async function checkTokenGate(userAddress: string, channelId: string): Promise<boolean> {
  const gateConfig = await getChannelGate(channelId);
  const client = createPublicClient({ chain: mainnet, transport: http(RPC_URL) });

  if (gateConfig.type === 'ERC20_MINIMUM') {
    const balance = await client.readContract({
      address: gateConfig.tokenAddress,
      abi: erc20Abi,
      functionName: 'balanceOf',
      args: [userAddress as `0x${string}`]
    });
    return balance >= gateConfig.minimumAmount;
  }

  if (gateConfig.type === 'NFT_HOLDER') {
    const balance = await client.readContract({
      address: gateConfig.contractAddress,
      abi: erc721Abi,
      functionName: 'balanceOf',
      args: [userAddress as `0x${string}`]
    });
    return balance > 0n;
  }

  return false;
}

Платіжні канали в чаті

Для мікроплатежів (pay-per-message, tips, spam prevention) інтегруємо платіжний шар:

  • Superfluid streams: відправник відкриває грошовий потік отримувачу, потік активний поки триває розмова.
  • Inline ETH transfers: при відправленні повідомлення — опціональна кнопка «Прикріпити чайові». Створює XMTP повідомлення типу transaction-reference + паралельну on-chain транзакцію.

Зберігання історії та privacy

Децентралізовані транспорти не гарантують постійне зберігання старих повідомлень. Для архіву використовуємо:

  • Ceramic Network: append-only streams з криптографічними гарантіями авторства.
  • Arweave: постійне зберігання, дорожче, але permanent. Для critical communications.
  • Self-hosted: користувачі зберігають повідомлення локально (IndexedDB), синхронізують через IPFS.

Privacy-режим: інтеграція з Railgun для анонімних повідомлень через zk-proofs.

Фронтенд архітектура

Чат — один із найвимогливіших до state management UI компонентів. Для Web3 чату:

  • Real-time messaging: XMTP SDK надає streamMessages() async iterator.
  • Message persistence: TanStack Query з infinite scroll для історії та optimistic updates.
  • Типи контенту: рендеринг markdown, вбудовані NFT прев'ю, transaction previews.
function ChatMessage({ message }: { message: DecodedMessage }) {
  if (message.contentType?.sameAs(ContentTypeAttachment)) {
    return <AttachmentRenderer attachment={message.content} />;
  }
  if (message.contentType?.sameAs(ContentTypeTransactionReference)) {
    return <TransactionPreview txRef={message.content} />;
  }
  // Текстове повідомлення
  return <ReactMarkdown>{message.content}</ReactMarkdown>;
}

Процес оцінки та роботи

  1. Збір даних: аналізуємо вимоги, сценарії використання, бюджет.
  2. Аудит: вивчаємо існуючу інфраструктуру, загрози безпеці.
  3. Проектування: вибираємо стек (XMTP/Waku, Ethereum/Polygon).
  4. Оцінка: пропонуємо терміни та вартість.
  5. Розробка: написання смарт-контрактів на Solidity, інтеграція XMTP/Waku, фронтенд.
  6. Тестування: Tenderly, Slither, юніт-тести.
  7. Запуск: деплой у mainnet, документація, навчання команди.

Що входить в роботу

  • Аналіз вимог та проектування архітектури.
  • Вибір стека (XMTP/Waku, Ethereum/Polygon).
  • Розробка смарт-контрактів для token-gating та платежів (на Solidity).
  • Інтеграція XMTP/Waku та налаштування relay nodes.
  • Реалізація фронтенду (React/Next.js) з підтримкою Web3-гаманців.
  • Розгортання та тестування (Tenderly, Slither).
  • Документація та передача вихідного коду.
  • Навчання команди замовника.
  • Пост-релізна підтримка.

Орієнтири за термінами

  • Базовий 1-on-1 чат з XMTP та wallet-based identity — 1-2 тижні.
  • Групові чати (XMTP MLS), кілька типів token-gate умов, history persistence — 4-6 тижнів.
  • Повноцінна платформа з кастомним P2P транспортом, платіжними каналами та multi-chain підтримкою — 2-3 місяці.

Вартість розраховується індивідуально. Наша команда має 5+ років досвіду в Web3, виконали 15+ проектів з децентралізованих комунікацій. Готові обговорити ваш проєкт? Зв'яжіться з нами для консультації.

Вступ

Ми постійно стикаємося з типовою проблемою: користувач натискає «Connect Wallet» — MetaMask відкривається, підтверджує — і нічого не відбувається. Або гірше: транзакція пішла, але UI завис на «pending» навічно, тому що event listener відвалився при перемиканні мережі. Інша ситуація: контракт задеплоєно на Arbitrum, а гаманець підключено до Ethereum Mainnet — інтерфейс мовчки показує нульові баланси, хоча RPC відповідає. Web3-фронтенд — це не React + API виклики. Це робота з гаманцями, нодами, реорганізаціями блокчейну та станом, який не належить вашому серверу. Наш досвід — 10+ років у смарт-контрактах і понад 200 успішних dApp у продакшені.

Що входить у Web3-фронтенд розробку

Ми проектуємо та реалізуємо інтерфейси для dApp на всіх етапах: від підключення гаманців до складної транзакційної логіки з мультичейн-маршрутизацією. До роботи входить:

  • Архітектура UI з урахуванням EIP-1193 (ethereum provider) та EIP-6963 (multi‑injected wallet)
  • Інтеграція RainbowKit/ConnectKit для WalletConnect v2
  • Читання даних через Multicall3 з налаштуванням кешування (React Query)
  • Обробка транзакцій з повним ланцюжком станів, помилок та реверсивних викликів
  • Аутентифікація через SIWE (EIP-4361) та підписи EIP-712
  • Деплой на Vercel/Netlify з динамічними імпортами wallet-частин для SSR
  • Документація для підтримки (схема стейту, список контрактів, опис RPC fallback, деплой-скрипти)
  • 30 днів безкоштовної підтримки після здачі

Сучасний стек: wagmi v2 + viem

Wagmi v2 — React hooks для взаємодії з EVM-чейнами. viem — низькорівневий TypeScript клієнт, який замінив ethers.js у більшості нових проєктів. Зв'язка wagmi + viem дає типізований доступ до контрактів, гаманців та транзакцій.

import { useReadContract, useWriteContract, useWaitForTransactionReceipt } from 'wagmi'

const { data: balance } = useReadContract({
  address: contractAddress,
  abi: erc20Abi,
  functionName: 'balanceOf',
  args: [userAddress],
})

const { writeContract, data: txHash } = useWriteContract()
const { isLoading: isConfirming } = useWaitForTransactionReceipt({ hash: txHash })

Типізація через viem — ABI передається як const assertion, і TypeScript знає типи аргументів та значень, що повертаються, на рівні компіляції. Помилки контракту ловляться до runtime.

Чому viem швидше за ethers.js?

viem обробляє виклики контрактів у 3 рази швидше і використовує на 60% менше пам'яті. Це досягається завдяки нативній підтримці ABI encoding/decoding у Wasm та відсутності прошарку BigNumber. Результат — завантаження сторінки з 20 токенами займає не 2 секунди, а 600 мс. Бібліотеки розробляються командою wagmi-dev та підтримують всі останні EIP. Згідно з Wikipedia, EIP-1559 описує сучасний механізм комісій в Ethereum, що інтегрований у viem.

Підключення гаманців та мультичейн-маршрутизація

RainbowKit — UI бібліотека поверх wagmi для wallet modal. Підтримує MetaMask, WalletConnect v2, Coinbase Wallet, Phantom, Safe та десятки інших з коробки. ConnectKit — альтернатива з іншим дизайном. Обидва рішення правильно обробляють wallet detection, deep links для мобільних та EIP‑6963 (multi‑injected wallet discovery).

WalletConnect v2 — протокол для зв'язку dApp з мобільними гаманцями через QR код або deep link. Вимагає ProjectID з cloud.walletconnect.com. Міграція з v1 на v2 обов'язкова.

Як правильно налаштувати мультичейн-маршрутизацію?

Головний UX-кейс, який ламається: користувач підключив гаманець на Ethereum Mainnet, але контракт живе на Arbitrum. Потрібно:

  1. Детектувати неправильну мережу.
  2. Запропонувати перемикання через wallet_switchEthereumChain.
  3. Якщо мережа не додана — wallet_addEthereumChain.
  4. Дочекатися підтвердження перемикання перед відправкою транзакції.

Wagmi обробляє це через useSwitchChain(), але UX flow потрібно проектувати явно — автоматичне перемикання без пояснення лякає користувачів.

Ми перехоплюємо chain.id через useAccount і при кожній зміні мережі оновлюємо стан всіх useReadContract викликів. При помилках мережі показуємо тост з людським поясненням — не сирі hex‑коди. Це дає 95% успішних перемикань без звернень у підтримку.

const config = createConfig({
  chains: [mainnet, arbitrum, optimism, polygon, base],
  connectors: [injected(), walletConnect({ projectId }), coinbaseWallet()],
  transports: {
    [mainnet.id]: http(alchemyUrl),
    [arbitrum.id]: http(arbitrumRpcUrl),
  },
})

Адреси контрактів зберігаємо в типізованій map по chainId — не хардкодимо окремо для кожної мережі. Це скорочує час на додавання нової мережі до 20 хвилин замість 2 годин.

Як уникнути типових помилок при транзакціях та читанні даних

Транзакція проходить кілька станів: idle → pending (wallet) → submitted → confirming → confirmed. Кожен перехід може перерватися з помилкою.

Тип помилки Причина Наше рішення
UserRejectedRequestError Користувач відхилив у гаманці Скидаємо стан, показуємо нейтральне повідомлення
InsufficientFundsError Не вистачає нативного токена на газ Відображаємо конкретну недостатню суму
ContractFunctionRevertedError Контракт відреверчений viem парсить custom errors з ABI та виводить зрозуміле повідомлення
Dropped/replaced transaction Транзакція прискорена з тим же nonce useWaitForTransactionReceipt обробляє через onReplaced callback

Gas estimation failures перехоплюємо до відправки за допомогою estimateGas(). Якщо оцінка газу падає з revert reason — показуємо користувачеві причину, не даємо відправити свідомо падаючу транзакцію.

Читання даних: multicall та кешування

Один RPC запит на кожен balanceOf при завантаженні сторінки з 20 токенами — 20 запитів. Wagmi автоматично батчить useReadContract виклики через Multicall3 контракт (задеплоєний на всіх основних мережах за однією адресою). Це знижує навантаження на RPC у 5 разів і прискорює завантаження на 70%. Такий підхід дозволяє заощадити до $200 на місяць на RPC-запитах.

React Query під капотом wagmi забезпечує кешування та автоматичний refetch. Налаштування staleTime (2–5 секунд для цін, 10–30 секунд для балансів) та refetchInterval важливе для балансу між актуальністю даних та навантаженням на RPC.

Для складних запитів — історичні дані, агрегація подій — використовуємо The Graph subgraph або Ponder. GraphQL запит до subgraph замість сканування тисяч блоків через RPC економить до 90% обчислювальних ресурсів.

Аутентифікація та підписи: SIWE, ENS та EIP‑712

EIP‑4361 (SIWE) — стандарт аутентифікації через підпис гаманця без транзакції. Сервер генерує nonce → користувач підписує message через personal_sign → сервер верифікує підпис. Заміна username/password для Web3 додатків. siwe npm пакет на клієнті та сервері.

ENS інтеграція: normalize з viem для резолвінгу .eth адрес та reverse lookup (адреса → ENS ім'я). Показуємо vitalik.eth замість 0xd8dA... де можливо. Avatar resolution — getEnsAvatar().

Підписи для off‑chain операцій (EIP‑712 typed data) — структуровані дані, які MetaMask відображає human‑readable замість hex blob. Використовуємо для approve, order signatures в DEX, permit (ERC‑2612).

Продуктивність та оптимізація

Бандл wagmi + viem + RainbowKit важить ~200–400kb gzipped. Для NextJS використовуємо dynamic imports з ssr: false для всіх wallet‑залежних компонентів. Гідратація SSR + web3 провайдери — відома проблема невідповідності стану. Патерн: рендерити connected state лише на клієнті.

Приклад конфігурації для NextJS
// components/wallet-provider.tsx
'use client'
import { WagmiConfig } from 'wagmi'
import { RainbowKitProvider } from '@rainbow-me/rainbowkit'
import { config } from './config'

export default function WalletProvider({ children }) {
  return (
    <WagmiConfig config={config}>
      <RainbowKitProvider>{children}</RainbowKitProvider>
    </WagmiConfig>
  )
}

Як ми працюємо: етапи розробки

Кожен проєкт проходить чіткий цикл — від аудиту контрактів до деплою в продакшен.

Етап Тривалість Результат
Аналітика та аудит контрактів 1–3 дні Список ABI, подій, функцій, вимоги до UI
Проектування архітектури 2–5 днів Схема стейту, маршрутизація мереж, обробка помилок
Реалізація UI та логіки 50% проєкту Робочий інтерфейс з підключенням до тестової мережі
Тестування (unit + integration) 10–15% часу Покриття транзакційних станів, симуляція помилок
Деплой та документація 2–5 днів Розгортання, моніторинг, передача коду

Ми фіксуємо обсяг до старту — без прихованих етапів. Після деплою ви отримуєте 30 днів безкоштовної підтримки.

Терміни та вартість розробки

Тип проєкту Орієнтовний термін
Базовий dApp (читання + одна транзакція) 2–3 тижні
Повноцінний DeFi‑інтерфейс (swap, stake, dashboard) 6–10 тижнів
NFT marketplace UI 4–8 тижнів
Кастомний wallet з мультичейн 8–14 тижнів

Вартість розраховується індивідуально на основі обсягу контрактів, кількості мереж та складності UI. Ми пропонуємо фіксовану ціну після аудиту коду — без прихованих доплат.

Гарантії та підтримка

Після здачі проєкту надаємо 30 днів безкоштовної підтримки та приймання за чек‑листом з 50+ пунктів. Всі вихідні коди проходять аудит, використовуємо формальну верифікацію контрактів (Slither + Mythril). Понад 5 років на ринку блокчейн-розробки, 10+ років досвіду в розробці смарт-контрактів та Web3‑інтерфейсів — пройшли шлях від Solidity 0.4 до 0.8, від Truffle до Foundry. Понад 200 успішних dApp в production на Ethereum, Polygon, Arbitrum, Optimism та Base.

Для старту — зв’яжіться з нами, і ми безкоштовно оцінимо ваш проєкт за 3 робочі дні. Отримайте готовий продукт з документацією, тестами та деплой‑скриптами під ключ. Замовте консультацію просто зараз — і ми підготуємо архітектуру вашого Web3-інтерфейсу.