Lens Protocol Integration
Lens Protocol—decentralized social graph on Polygon. Your application becomes one of the clients of a unified protocol: users bring their profile, followers and content from other Lens-compatible applications. This network effect without needing to build social graph from scratch.
What is Lens Protocol
Lens works on the principle: user owns their social graph as NFT. Profile—this is ERC-721, Follow—ERC-721 from each follower. Publications, mirrors, comments—on-chain transactions (but gas can be sponsored).
Key components:
- LensHub—main contract, manages profiles and publications
- Open Action Modules—custom actions on collect/interact (monetization)
- Follow Modules—subscription logic (paid, NFT-gate, etc.)
- Lens API—GraphQL API for indexed data
SDK Setup
import { LensClient, production, SessionType } from "@lens-protocol/client";
import { providers } from "ethers";
const lensClient = new LensClient({
environment: production,
});
// Authentication via wallet
async function authenticateWithLens(
walletClient: WalletClient,
address: string
): Promise<void> {
const profileManaged = await lensClient.profile.fetchAll({
where: { ownedBy: [address] },
});
if (profileManaged.items.length === 0) {
throw new Error("No Lens profile found");
}
const profile = profileManaged.items[0];
// Login creates session with EIP-712 signature
const session = await lensClient.login({
onboardingUser: {
app: process.env.LENS_APP_ADDRESS!,
wallet: walletClient,
},
});
}
Core Operations
Publication Feed
// Get feed for user (publications from those they follow)
const feed = await lensClient.feed.fetch({
where: {
for: profileId,
},
limit: LimitType.TwentyFive,
});
// Get publications from specific profile
const publications = await lensClient.publication.fetchAll({
where: {
from: [profileId],
publicationTypes: [PublicationType.Post],
},
orderBy: PublicationsOrderByType.Latest,
});
// Pagination
if (publications.pageInfo.next) {
const nextPage = await lensClient.publication.fetchAll({
where: { from: [profileId] },
cursor: publications.pageInfo.next,
});
}
Publication with Image
import { image } from "@lens-protocol/metadata";
import { StorageClient } from "@lens-protocol/storage-node-client";
const storageClient = StorageClient.create();
async function postWithImage(
file: File,
caption: string
): Promise<string> {
// Upload image to IPFS via Lens storage
const imageResult = await storageClient.uploadFile(file);
// Create metadata
const metadata = image({
title: caption,
image: {
item: imageResult.uri,
type: MediaImageMimeType.Jpeg,
},
content: caption,
locale: "en",
tags: ["photography"],
});
// Upload metadata
const metadataResult = await storageClient.uploadAsJson(metadata);
// Publish
const result = await sessionClient.publication.postOnchain({
contentURI: metadataResult.uri,
});
return result.id;
}
Follow and Check Subscription
// Follow
const followResult = await sessionClient.follow.follow({
follow: [{ profileId: targetProfileId }],
});
// Check subscription
const isFollowing = await lensClient.profile.following({
for: followerProfileId,
});
const isFollowingTarget = isFollowing.items.some(
p => p.id === targetProfileId
);
// List of profile followers
const followers = await lensClient.profile.followers({
of: profileId,
limit: LimitType.Fifty,
});
Open Actions (Collect, Tip)
// Collect publication
const collectResult = await sessionClient.publication.actions.actOn({
actOn: { simpleCollectOpenAction: true },
for: publicationId,
});
// Custom tip via Open Action
const tipResult = await sessionClient.publication.actions.actOn({
actOn: {
unknownOpenAction: {
address: TIP_ACTION_MODULE_ADDRESS,
data: encodeAbiParameters(
[{ type: "address" }, { type: "uint256" }],
[recipient, tipAmount]
),
},
},
for: publicationId,
});
Notifications
// Notifications for user (mentions, follows, collects)
const notifications = await lensClient.notifications.fetch({
where: {
publishedOn: [process.env.LENS_APP_ADDRESS!],
},
});
for (const notification of notifications.items) {
switch (notification.__typename) {
case "FollowNotification":
console.log(`New follower: ${notification.followers[0].handle?.fullHandle}`);
break;
case "CommentNotification":
console.log(`New comment on ${notification.publication.id}`);
break;
case "MentionNotification":
console.log(`Mentioned in ${notification.publication.id}`);
break;
case "ActedNotification":
console.log(`Someone collected ${notification.publication.id}`);
break;
}
}
Profile Creation
// Create new Lens profile
const createProfileResult = await lensClient.wallet.createProfileWithHandle({
handle: "myhandle",
to: walletAddress,
});
// Update profile metadata
const profileMetadata = profile({
name: "Alice",
bio: "Web3 developer and creator",
picture: "ipfs://QmAvatarCID",
coverPicture: "ipfs://QmCoverCID",
attributes: [
{ key: "twitter", value: "@alice", type: MetadataAttributeType.String },
{ key: "website", value: "https://alice.xyz", type: MetadataAttributeType.String },
],
});
const metadataURI = await storageClient.uploadAsJson(profileMetadata);
await sessionClient.profile.setProfileMetadata({
metadataURI,
});
Lens + TheGraph for Custom Queries
Lens provides its own API, but for specific queries you can call TheGraph directly:
import { createClient } from "@urql/core";
const LENS_SUBGRAPH = "https://api.thegraph.com/subgraphs/name/lens-protocol/lens-polygon-mainnet";
const client = createClient({ url: LENS_SUBGRAPH });
// Top authors by collect count in last 7 days
const TOP_CREATORS = `
query TopCreators($since: Int!) {
publications(
where: { timestamp_gt: $since, collectCount_gt: 10 }
orderBy: collectCount
orderDirection: desc
first: 20
) {
id
profile {
handle
followersCount
}
collectCount
metadata {
content
}
}
}
`;
const weekAgo = Math.floor(Date.now() / 1000) - 7 * 24 * 3600;
const result = await client.query(TOP_CREATORS, { since: weekAgo }).toPromise();
Integrating Lens Protocol into existing application—2-4 weeks. Includes: SDK setup, core CRUD operations (profile, posts, follows), notifications and UI components. Lens removes the task of building social graph from you—you get ready ecosystem audience.







