Розробка децентралізованої соціальної мережі
Децентралізована соціальна мережа—одна з найбільш технічно та продуктово складних задач у Web3. Проблеми масштабування, стійкість до цензури, власність даних, монетизація без прив'язання до постачальника—все це потрібно вирішити одночасно. Lens Protocol та Farcaster пропонують різні відповіді на ці питання.
Архітектурні підходи
Повністю On-chain (Lens Protocol)
Усі соціальні операції (публікації, підписки, коментарі, перепости)—транзакції в блокчейні (Polygon). Контент—хеш IPFS, метаданні в блокчейні.
Переваги: максимальна стійкість до цензури, сумісність (будь-який додаток працює з одними й тими ж даними), портативна ідентичність.
Недоліки: газ за кожну дію (навіть на L2), затримка блокчейна видна користувачу.
Off-chain з On-chain якорюванням (Farcaster)
Повідомлення зберігаються на Hubs (федеративні сервери), тільки ідентичність закріплена в блокчейні (Ethereum). Hubs синхронізуються один з одним через протокол gossip.
Переваги: швидко, без газу за кожне повідомлення, масштабувально.
Недоліки: залежність від Hubs (можуть цензурувати), менше trustless.
ActivityPub + ідентичність блокчейну (гібрид)
ActivityPub (протокол Mastodon, Bluesky) + аутентифікація Ethereum. Федеративна соціальна мережа з крипто-гаманцем як ідентифікатором.
Lens Protocol—On-chain соціальний граф
Ключові концепції
Profile NFT: кожен користувач = ERC-721 NFT. Трансферабельний—можна продати акаунт з аудиторією.
Publication: пост, коментар, дзеркало (репост). Зберігається як calldata транзакції (контент на IPFS, хеш в блокчейні).
Follow NFT: послідовник отримує NFT, що підтверджує підписку. Трансферабельний—можна продати «місце послідовника».
Collect: монетизація публікації—читачі платять за collect NFT (копію публікації).
Модулі: користувацька логіка для follow (платити за follow), collect (платити за collect, NFT-gate), reference (тільки послідовники можуть коментувати).
Інтеграція з Lens API
import { LensClient, development, production } from "@lens-protocol/client";
const lensClient = new LensClient({
environment: production,
});
// Отримати профіль
const profile = await lensClient.profile.fetch({
forHandle: "lens/stani",
});
// Публікувати пост
async function createPost(
profileId: string,
content: string,
imageUrl?: string
): Promise<string> {
// Завантажити метаданні в IPFS
const metadata = {
$schema: "https://json-schemas.lens.dev/publications/text-only/3.0.0/schema.json",
lens: {
id: uuidv4(),
content,
locale: "en",
mainContentFocus: "TEXT_ONLY",
tags: [],
},
};
const metadataURI = await uploadToIPFS(metadata);
// Створити пост через Lens API
const result = await lensClient.publication.postOnchain({
contentURI: metadataURI,
});
return result.id;
}
// Слідкувати за користувачем
async function followProfile(profileId: string, followerProfileId: string) {
const result = await lensClient.follow.follow({
follow: [{ profileId }],
});
// result містить gasless транзакцію через Lens Sponsored
return result;
}
Механіка Collect (Монетизація)
// Пост з платною колекцією (1 WMATIC = здатність до збору)
const postWithCollect = await lensClient.publication.postOnchain({
contentURI: metadataURI,
openActionModules: [
{
collectOpenAction: {
simpleCollectOpenAction: {
amount: {
currency: "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", // WMATIC
value: "1",
},
recipient: creatorAddress,
referralFee: 5, // 5% йде тому, хто поділився (mirror)
followerOnly: true, // тільки послідовники можуть збирати
},
},
},
],
});
Gasless через Lens Sponsored Transactions
Lens підтримує gasless транзакції через ERC-4337—користувачі не платять MATIC:
const sessionClient = await lensClient.login({
onboardingUser: {
app: "0xYourAppAddress",
wallet: walletClient,
},
});
// Тепер транзакції спонсовані—Lens платить газ
const result = await sessionClient.publication.postOnchain({
contentURI: metadataURI,
});
Архітектура користувацької децентралізованої соціальної мережі
Якщо потрібна повна незалежність—будуємо власний протокол:
Ідентичність
contract SocialIdentity is ERC721 {
struct Profile {
string handle; // унікальне ім'я користувача
string metadataURI; // IPFS CID з біо, аватаром
uint256 followerCount;
uint256 followingCount;
uint256 publicationCount;
}
mapping(string => uint256) public handleToTokenId;
mapping(uint256 => Profile) public profiles;
function createProfile(string calldata handle, string calldata metadataURI)
external returns (uint256 tokenId)
{
require(handleToTokenId[handle] == 0, "Handle taken");
require(bytes(handle).length >= 3 && bytes(handle).length <= 31, "Invalid handle length");
tokenId = ++_tokenCounter;
_mint(msg.sender, tokenId);
profiles[tokenId] = Profile({
handle: handle,
metadataURI: metadataURI,
followerCount: 0,
followingCount: 0,
publicationCount: 0,
});
handleToTokenId[handle] = tokenId;
emit ProfileCreated(tokenId, handle, msg.sender);
}
}
Публікації
contract Publications {
enum PublicationType { POST, COMMENT, REPOST }
struct Publication {
uint256 profileId;
string contentURI; // IPFS CID
PublicationType pubType;
uint256 parentId; // для коментаря/перепосту
uint256 timestamp;
uint256 collectCount;
uint256 commentCount;
uint256 mirrorCount;
}
mapping(uint256 => Publication) public publications;
function post(uint256 profileId, string calldata contentURI)
external returns (uint256 pubId)
{
require(socialIdentity.ownerOf(profileId) == msg.sender, "Not profile owner");
pubId = ++_publicationCounter;
publications[pubId] = Publication({
profileId: profileId,
contentURI: contentURI,
pubType: PublicationType.POST,
parentId: 0,
timestamp: block.timestamp,
collectCount: 0,
commentCount: 0,
mirrorCount: 0,
});
// Оновити лічильник
socialIdentity.incrementPublicationCount(profileId);
emit Posted(pubId, profileId, contentURI);
}
}
Соціальний граф (Підписки)
contract SocialGraph {
// послідовник → набір того, за ким слідкує
mapping(uint256 => mapping(uint256 => bool)) public isFollowing;
// Follow NFT: можна продати
mapping(uint256 => mapping(uint256 => address)) public followNFTOwner;
function follow(uint256 followerProfileId, uint256 targetProfileId) external {
require(!isFollowing[followerProfileId][targetProfileId], "Already following");
require(
socialIdentity.ownerOf(followerProfileId) == msg.sender,
"Not profile owner"
);
isFollowing[followerProfileId][targetProfileId] = true;
// Mint Follow NFT
uint256 followNFTId = _mintFollowNFT(followerProfileId, targetProfileId);
followNFTOwner[followerProfileId][targetProfileId] = msg.sender;
socialIdentity.incrementFollowerCount(targetProfileId);
socialIdentity.incrementFollowingCount(followerProfileId);
emit Followed(followerProfileId, targetProfileId, followNFTId);
}
}
Контент та зберігання
IPFS через Web3.Storage або Pinata. Публікації зберігаються як JSON метаданні на IPFS:
interface PublicationMetadata {
version: "2.0.0";
mainContentFocus: "TEXT_ONLY" | "IMAGE" | "VIDEO" | "ARTICLE";
content: string;
image?: string; // IPFS CID зображення
media?: MediaItem[];
locale: string;
tags: string[];
appId: string; // ваш appId
}
Ceramic/ComposeDB—децентралізована база даних над IPFS для мутабельних даних (редагування профілю, налаштування).
TheGraph—індексування on-chain подій для швидких запитів:
query GetProfileFeed($profileId: String!, $cursor: String) {
publications(
where: { author: $profileId }
orderBy: timestamp
orderDirection: desc
first: 20
after: $cursor
) {
id
contentURI
timestamp
collectCount
commentCount
comments(first: 3, orderBy: timestamp, orderDirection: desc) {
id
contentURI
author { handle }
}
}
}
Модерація в децентралізованій мережі
Протиріччя: стійкість до цензури vs небажаний контент. Варіанти:
Мітки/флаги: on-chain маркування (підхід Bluesky Labeler)—контент сам по собі не видаляється, але позначається. Додатки вирішують, що показувати.
Фільтрація на боці клієнта: додатки фільтрують на рівні UI, а не протоколу. Стійкий до цензури протокол, але модеровані клієнти.
Управління спільнотою: DAO голосує за видалення контенту з індексаторів. Компромісс.
Монетизація для контент-творців
- Комісії за збір: читачі платять за збір (виключний контент)
- Subscription NFT: місячний абонемент → доступ до преміум контенту
- Чайові: мікроплатежі через контракт (або L2 для економії газу)
- Гейтинг токенів: тільки власники певного NFT бачать контент
- Доход від реклами в токенах: протокол розподіляє дохід від реклами між творцями
Стек
| Компонент | Технологія |
|---|---|
| Ідентичність | Lens Protocol або користувацький ERC-721 |
| Зберігання | IPFS (Pinata) + Ceramic |
| Індексування | TheGraph + Lens API |
| Фронтенд | Next.js + wagmi + viem |
| Real-time | WebSocket (реакції, сповіщення) |
| L2 | Polygon (Lens native) |
Сроки
- Додаток на Lens Protocol (профіль + стрічка + пост + follow): 6-10 тижнів
- Користувацький протокол (власні контракти + повний стек): 4-6 місяців
- Модерація + управління: +4-6 тижнів
- Мобільний додаток: +8-12 тижнів
- Аудит безпеки: обов'язковий для користувацького протоколу







