Разработка чата на базе блокчейна
Чат «на блокчейне» — понятие, которое требует немедленного уточнения. Хранить каждое сообщение on-chain на Ethereum mainnet стоит $2-10 за сообщение при нормальном gas. Это не chat, это дорогостоящий публичный реестр. Реальная задача — спроектировать систему, где блокчейн используется там, где он нужен: identity, ключевое управление, платёжные каналы, proof of existence, — а сами сообщения передаются через cryptographically secured, decentralized transport.
Пространство решений: от on-chain до hybrid
Полностью on-chain: только для специфичных случаев
Хранение сообщений on-chain имеет смысл в очень узких сценариях:
- Governance proposals и обсуждения (Snapshot, Tally) — immutability важна
- Dispute resolution в арбитражных протоколах — evidence должен быть tamper-proof
- 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-50x дешевле.
P2P с on-chain identity: XMTP
XMTP (Extensible Message Transport Protocol) — production-ready протокол для Web3 сообщений. Это де-факто стандарт для decentralized chat в 2024. Используется в Coinbase Wallet, Converse, множестве dApps.
Архитектура XMTP:
- Identity базируется на Ethereum адресе. Не нужен отдельный аккаунт.
- Сообщения шифруются end-to-end через X3DH (Extended Triple Diffie-Hellman) — тот же протокол, что Signal.
- Транспорт — децентрализованная P2P сеть XMTP nodes.
- On-chain: только ключевая информация при первой регистрации пользователя.
import { Client } from '@xmtp/xmtp-js';
import { ethers } from 'ethers';
// Инициализация клиента — подпись XMTP ключей кошельком
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 (2024) добавил группы на базе MLS (Messaging Layer Security, RFC 9420) — криптографический протокол для группового шифрования с 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']); // forward secrecy: ключи ротируются
Waku: decentralized transport без identity layer
Waku (Status протокол, сейчас автономный проект) — P2P транспорт для сообщений без централизованных серверов. Подходит когда нужен только messaging без Web3 identity.
Waku использует libp2p и gossipsub. Сообщения имеют TTL, не хранятся постоянно. Для постоянства — комбинировать с Waku Store протоколом (offline messages) или внешним хранилищем.
import { createLightNode, waitForRemotePeer } from '@waku/sdk';
import { createEncoder, createDecoder } from '@waku/sdk';
const waku = await createLightNode({ defaultBootstrap: true });
await waitForRemotePeer(waku);
const contentTopic = '/my-chat/1/messages/proto';
const encoder = createEncoder({ contentTopic });
const decoder = createDecoder(contentTopic);
// Подписка на сообщения
await waku.filter.subscribe([decoder], (message) => {
if (message.payload) {
const decoded = ChatMessage.decode(message.payload); // Protobuf
console.log(decoded.text);
}
});
// Отправка
await waku.lightPush.send(encoder, {
payload: ChatMessage.encode({ text: 'hello', sender: address }).finish()
});
Waku используется Status, Railgun, и рядом других Web3 проектов.
Token-gated чаты
Ограничение доступа к чату на основе on-chain условий — распространённый паттерн для DAO и NFT коллекций.
Проверка на бэкенде (если есть backend)
// Middleware проверки токен-гейтинга
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;
}
Бессерверный token-gate через XMTP
XMTP не имеет встроенного token-gating. Но можно реализовать на уровне приложения: при попытке вступить в группу, вызывающий подписывает attestation своего on-chain статуса. Существующие участники верифицируют через Ethereum provider прежде чем принять addMembers.
Для более сложных сценариев — Sign-In With Ethereum (EIP-4361) + Lit Protocol условия: только кошелёк с нужным NFT может получить ключ расшифровки канала.
Платёжные каналы в чате
Для микроплатежей за сообщения (pay-per-message модели, tip системы, spam prevention) — интеграция платёжного layer:
Superfluid streams: отправитель открывает денежный поток получателю, поток активен пока идёт разговор. Закрытие разговора = закрытие потока. Реализуется через Superfluid SDK + хуки в UI.
Inline ETH transfers: при отправке сообщения — опциональная кнопка «Приложить чаевые». Создаёт XMTP сообщение специального content type transaction-reference + параллельную on-chain транзакцию.
Хранение истории и privacy
Децентрализованные транспорты (XMTP, Waku) не гарантируют постоянное хранение старых сообщений. Для архива:
- Ceramic Network: append-only streams с криптографическими гарантиями авторства
- Arweave: постоянное хранение, дороже, но permanent. Используется для critical communications
- Self-hosted: пользователи сами хранят свои сообщения локально (IndexedDB), синхронизируют через IPFS
Privacy-режим: Railgun интеграция для анонимных сообщений — sender и receiver зашифрованы через zk-proofs. Нишевый, но существующий usecase.
Фронтенд архитектура
Чат — один из самых требовательных к state management UI компонентов. Для Web3 чата:
Real-time messaging: WebSocket или SSE для XMTP relay, либо polling (неэффективно). XMTP JS SDK имеет встроенный streamMessages() async iterator.
Message persistence: TanStack Query с infinite scroll для истории. Optimistic updates для только что отправленных сообщений — сообщение показывается немедленно, статус pending меняется на sent при подтверждении.
Типы контента: рендеринг markdown, встроенные NFT превью (через opensea/simplehash API), transaction previews для embedded tx ссылок.
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>;
}
Стек разработки
| Компонент | Технология |
|---|---|
| Messaging protocol | XMTP v3 |
| P2P transport (альтернатива) | Waku SDK |
| Identity | Ethereum + EIP-4361 |
| Token-gating | viem + кастомная логика |
| Payment streams | Superfluid SDK |
| Frontend | Next.js / React + wagmi |
| State management | Zustand + TanStack Query |
| Storage (archive) | Ceramic или Arweave |
Ориентиры по срокам
Базовый 1-on-1 чат с XMTP, wallet-based identity и token-gating для одного контракта — 1-2 недели. Групповые чаты (XMTP MLS), несколько типов token-gate условий, history persistence, embedded transactions и мобильная адаптация — 4-6 недель. Полноценная платформа с кастомным P2P транспортом, платёжными каналами, admin инструментами и multi-chain поддержкой — 2-3 месяца.







