CTO linkcard.app 💸 Web3 Researcher & Investor
CTO linkcard.app 💸 Web3 Researcher & Investor

Subscribe to Fabrizio G

Subscribe to Fabrizio G
Share Dialog
Share Dialog
<100 subscribers
<100 subscribers



Introduction
Every time we grab the cell phone we are losing money. We are voluntarily providing our attention and information to some corporation which then exploits, manipulates and monetizes it without our consent.
Each platform owns all of our digital information and we cannot exercise any rights over it. Luckily web3 changes the paradigm. In this new era, users have control of their information, there are no centralized databases that can be sold or exploited. No need to fill out useless registration forms.
Demo App
In this article I will be showing you how to create a fully decentralized social application, independent of centralized services, using lens protocol, bundlr and arweave.
Checkout the GitHub repo | Checkout the demo
What we will learn:
Query lens protocol image posts
Query the default profile of the user
Uploading images to Arweave using bundlr
Change the lens profile with our arweave image

Arweave: It is a new type of storage that backs data with sustainable and perpetual endowments, allowing users and developers to truly store data forever — for the very first time. Read more
Bundlr: Bundlr makes web3 data storage on Arweave accessible by making it as fast, easy, and reliable as traditional data storage. Arweave is the only truly decentralized, permanent data storage solution. Read more
Lens: Lens Protocol is a user-owned, open social graph that any application can plug into. Read more
Step 1: Minting your lens profile For interacting with lens as the base protocol we will need first to create a profile. From the website we can request to claim a handle using your metamask.

Congrats! 👯♀️ You now own a Lens Profile, a portable Web3 social profile NFT. You can check mine and follow me here!
Step 2: Set up the application On your terminal run the following commands. We will create a directory and add the necessary dependencies.
npx create-nuxt-app lens-bundlr-app
cd lens-bundlr-app
code .
yarn add @bundlr-network/client bignumber.js ethers urql graphql
Now run this command yarn dev to see your app running on localhost:3000
Step 3: Components We will start working on the UI. For that we need to create a top nav which will have a button to connect to lens protocol using metamask.
async signIn() {
try {
const accounts = await window.ethereum.send( "eth_requestAccounts" )
const account = accounts.result[0]
const urqlClient = await this.$util.createClient()
const response = await urqlClient.query(getChallenge, {address: account }).toPromise()
const provider = new providers.Web3Provider(window.ethereum);
const signer = provider.getSigner()
const signature = await signer.signMessage(response.data.challenge.text)
const authData = await urqlClient.mutation(authenticate, {address: account, signature}).toPromise()
const { accessToken, refreshToken } = authData.data.authenticate
const accessTokenData = this.$util.parseJwt(accessToken)
localStorage.setItem(this.$util.STORAGE_KEY, JSON.stringify({
accessToken, refreshToken, exp: accessTokenData.exp
}))
window.location.reload()
} catch (err) {
console.log('error: ', err)
}
}
We will also have a modal for uploading images to arweave using the bundlr library. We fill need to fund our wallet first.
async uploadFile() {
try{
//Init bundlr
const provider = new providers.Web3Provider(window.ethereum);
await provider._ready()
const bundlr = new WebBundlr("https://node1.bundlr.network", "matic", provider)
await bundlr.ready()
this.bundlrRef = bundlr
this.bundlrRef.current = bundlr
this.loading=1
//Upload image
let tx = await this.bundlrRef.uploader.upload(this.file, [{ name: "Content-Type", value: "image/png" }])
console.log('tx: ', tx)
this.uri=`http://arweave.net/${tx.data.id}`
this.loading=2
//Update lens profile
await this.setProfilePhoto(this.uri,provider)
if(!alert('Success!')){window.location.reload();}
} catch(e){
console.log(e)
}
}
For setting our profile image we will be using the API of lens protocol, using our recently uploaded arweave image.
async setProfilePhoto(uri,provider) {
let dis=this
const urqlClient = await this.$util.createClient()
const dd = await urqlClient.query(defaultProfile, {request:{ethereumAddress: dis.wallet }}).toPromise()
let profile=dd.data.defaultProfile
const contract = new ethers.Contract( LENS_HUB_CONTRACT_ADDRESS, ABI,provider.getSigner() )
try {
const tx = await contract.setProfileImageURI(profile.id, uri)
await tx.wait()
} catch (err) {
console.log('error: ', err)
}
}
Step 4: Pages The Index page we are going to connect to lens protocol and retrieve our default profile using GraphQL.
export const defaultProfile = `
query($request: DefaultProfileRequest!) {
defaultProfile(request: $request) {
id
name
bio
isDefault
attributes {
displayType
traitType
key
value
}
followNftAddress
metadata
handle
picture {
... on NftImage {
contractAddress
tokenId
uri
chainId
verified
}
... on MediaSet {
original {
url
mimeType
}
}
}
coverPicture {
... on NftImage {
contractAddress
tokenId
uri
chainId
verified
}
... on MediaSet {
original {
url
mimeType
}
}
}
ownedBy
dispatcher {
address
canUseRelay
}
stats {
totalFollowers
totalFollowing
totalPosts
totalComments
totalMirrors
totalPublications
totalCollects
}
followModule {
... on FeeFollowModuleSettings {
type
contractAddress
amount {
asset {
name
symbol
decimals
address
}
value
}
recipient
}
... on ProfileFollowModuleSettings {
type
}
... on RevertFollowModuleSettings {
type
}
}
}
}`
Using this query we are going to fetch the profile and show it in the UI using this method.
async fetchProfile(wallet) {
try {
let dis= this
const urqlClient = await this.$util.createClient()
const dd = await urqlClient.query(defaultProfile, {request:{ethereumAddress: wallet }}).toPromise()
this.profile=dd.data.defaultProfile
} catch (err) {
console.log('error fetching profile...', err)
}
}
The Explore page will fetch the latest posts uploaded to Lens, filtering out only the images that are what we care for in this demo app, but you can fetch all types of posts.
async recommendProfiles() {
try {
const urqlClient = await this.$util.createClient()
const response = await urqlClient.query(recommendProfiles).toPromise()
const profileData = await Promise.all(response.data.recommendedProfiles.map(async profile => {
const pub = await urqlClient.query(getPublications, { id: profile.id, limit: 1 }).toPromise()
profile.publication = pub.data.publications.items[0]
return profile
}))
this.pubs=profileData
} catch (err) {
console.log('error fetching recommended profiles: ', err)
}
}
Finally, we need a way to fund our bundlr credits to keep uploading images to the Arweave blockchain. This section is the Balance page.
async fetchBalance() {
const provider = new providers.Web3Provider(window.ethereum);
await provider._ready()
const bundlr = new WebBundlr("https://node1.bundlr.network", "matic", provider)
await bundlr.ready()
this.bundlrRef = bundlr
this.bundlrRef.current = bundlr
this.$store.state.bundlrRef = bundlr
this.$store.state.bundlrRef.current = bundlr
const bal = await this.bundlrRef.current.getLoadedBalance()
console.log('bal: ', utils.formatEther(bal.toString()))
this.balance=utils.formatEther(bal.toString())
}
async fundWallet() {
try{
if (!this.amount) return
let response = await this.bundlrRef.fund(this.parseInput(this.amount))
console.log('Wallet funded: ', response)
fetchBalance()
}catch(e){
console.log(e)
}
}
That’s it! We are all set creating our first decentralized social application using decentralized storage.
Further Reading If you found this tutorial useful, you may also like these:
■ Permanent information ■ The end of signups ■ NFT Storage
Sources Useful resources and links I used to create this article
■ Full Stack Web3 with Lens Protocol, Next.js, and GraphQL ■ Lens docs ■ Bundlr docs

Introduction
Every time we grab the cell phone we are losing money. We are voluntarily providing our attention and information to some corporation which then exploits, manipulates and monetizes it without our consent.
Each platform owns all of our digital information and we cannot exercise any rights over it. Luckily web3 changes the paradigm. In this new era, users have control of their information, there are no centralized databases that can be sold or exploited. No need to fill out useless registration forms.
Demo App
In this article I will be showing you how to create a fully decentralized social application, independent of centralized services, using lens protocol, bundlr and arweave.
Checkout the GitHub repo | Checkout the demo
What we will learn:
Query lens protocol image posts
Query the default profile of the user
Uploading images to Arweave using bundlr
Change the lens profile with our arweave image

Arweave: It is a new type of storage that backs data with sustainable and perpetual endowments, allowing users and developers to truly store data forever — for the very first time. Read more
Bundlr: Bundlr makes web3 data storage on Arweave accessible by making it as fast, easy, and reliable as traditional data storage. Arweave is the only truly decentralized, permanent data storage solution. Read more
Lens: Lens Protocol is a user-owned, open social graph that any application can plug into. Read more
Step 1: Minting your lens profile For interacting with lens as the base protocol we will need first to create a profile. From the website we can request to claim a handle using your metamask.

Congrats! 👯♀️ You now own a Lens Profile, a portable Web3 social profile NFT. You can check mine and follow me here!
Step 2: Set up the application On your terminal run the following commands. We will create a directory and add the necessary dependencies.
npx create-nuxt-app lens-bundlr-app
cd lens-bundlr-app
code .
yarn add @bundlr-network/client bignumber.js ethers urql graphql
Now run this command yarn dev to see your app running on localhost:3000
Step 3: Components We will start working on the UI. For that we need to create a top nav which will have a button to connect to lens protocol using metamask.
async signIn() {
try {
const accounts = await window.ethereum.send( "eth_requestAccounts" )
const account = accounts.result[0]
const urqlClient = await this.$util.createClient()
const response = await urqlClient.query(getChallenge, {address: account }).toPromise()
const provider = new providers.Web3Provider(window.ethereum);
const signer = provider.getSigner()
const signature = await signer.signMessage(response.data.challenge.text)
const authData = await urqlClient.mutation(authenticate, {address: account, signature}).toPromise()
const { accessToken, refreshToken } = authData.data.authenticate
const accessTokenData = this.$util.parseJwt(accessToken)
localStorage.setItem(this.$util.STORAGE_KEY, JSON.stringify({
accessToken, refreshToken, exp: accessTokenData.exp
}))
window.location.reload()
} catch (err) {
console.log('error: ', err)
}
}
We will also have a modal for uploading images to arweave using the bundlr library. We fill need to fund our wallet first.
async uploadFile() {
try{
//Init bundlr
const provider = new providers.Web3Provider(window.ethereum);
await provider._ready()
const bundlr = new WebBundlr("https://node1.bundlr.network", "matic", provider)
await bundlr.ready()
this.bundlrRef = bundlr
this.bundlrRef.current = bundlr
this.loading=1
//Upload image
let tx = await this.bundlrRef.uploader.upload(this.file, [{ name: "Content-Type", value: "image/png" }])
console.log('tx: ', tx)
this.uri=`http://arweave.net/${tx.data.id}`
this.loading=2
//Update lens profile
await this.setProfilePhoto(this.uri,provider)
if(!alert('Success!')){window.location.reload();}
} catch(e){
console.log(e)
}
}
For setting our profile image we will be using the API of lens protocol, using our recently uploaded arweave image.
async setProfilePhoto(uri,provider) {
let dis=this
const urqlClient = await this.$util.createClient()
const dd = await urqlClient.query(defaultProfile, {request:{ethereumAddress: dis.wallet }}).toPromise()
let profile=dd.data.defaultProfile
const contract = new ethers.Contract( LENS_HUB_CONTRACT_ADDRESS, ABI,provider.getSigner() )
try {
const tx = await contract.setProfileImageURI(profile.id, uri)
await tx.wait()
} catch (err) {
console.log('error: ', err)
}
}
Step 4: Pages The Index page we are going to connect to lens protocol and retrieve our default profile using GraphQL.
export const defaultProfile = `
query($request: DefaultProfileRequest!) {
defaultProfile(request: $request) {
id
name
bio
isDefault
attributes {
displayType
traitType
key
value
}
followNftAddress
metadata
handle
picture {
... on NftImage {
contractAddress
tokenId
uri
chainId
verified
}
... on MediaSet {
original {
url
mimeType
}
}
}
coverPicture {
... on NftImage {
contractAddress
tokenId
uri
chainId
verified
}
... on MediaSet {
original {
url
mimeType
}
}
}
ownedBy
dispatcher {
address
canUseRelay
}
stats {
totalFollowers
totalFollowing
totalPosts
totalComments
totalMirrors
totalPublications
totalCollects
}
followModule {
... on FeeFollowModuleSettings {
type
contractAddress
amount {
asset {
name
symbol
decimals
address
}
value
}
recipient
}
... on ProfileFollowModuleSettings {
type
}
... on RevertFollowModuleSettings {
type
}
}
}
}`
Using this query we are going to fetch the profile and show it in the UI using this method.
async fetchProfile(wallet) {
try {
let dis= this
const urqlClient = await this.$util.createClient()
const dd = await urqlClient.query(defaultProfile, {request:{ethereumAddress: wallet }}).toPromise()
this.profile=dd.data.defaultProfile
} catch (err) {
console.log('error fetching profile...', err)
}
}
The Explore page will fetch the latest posts uploaded to Lens, filtering out only the images that are what we care for in this demo app, but you can fetch all types of posts.
async recommendProfiles() {
try {
const urqlClient = await this.$util.createClient()
const response = await urqlClient.query(recommendProfiles).toPromise()
const profileData = await Promise.all(response.data.recommendedProfiles.map(async profile => {
const pub = await urqlClient.query(getPublications, { id: profile.id, limit: 1 }).toPromise()
profile.publication = pub.data.publications.items[0]
return profile
}))
this.pubs=profileData
} catch (err) {
console.log('error fetching recommended profiles: ', err)
}
}
Finally, we need a way to fund our bundlr credits to keep uploading images to the Arweave blockchain. This section is the Balance page.
async fetchBalance() {
const provider = new providers.Web3Provider(window.ethereum);
await provider._ready()
const bundlr = new WebBundlr("https://node1.bundlr.network", "matic", provider)
await bundlr.ready()
this.bundlrRef = bundlr
this.bundlrRef.current = bundlr
this.$store.state.bundlrRef = bundlr
this.$store.state.bundlrRef.current = bundlr
const bal = await this.bundlrRef.current.getLoadedBalance()
console.log('bal: ', utils.formatEther(bal.toString()))
this.balance=utils.formatEther(bal.toString())
}
async fundWallet() {
try{
if (!this.amount) return
let response = await this.bundlrRef.fund(this.parseInput(this.amount))
console.log('Wallet funded: ', response)
fetchBalance()
}catch(e){
console.log(e)
}
}
That’s it! We are all set creating our first decentralized social application using decentralized storage.
Further Reading If you found this tutorial useful, you may also like these:
■ Permanent information ■ The end of signups ■ NFT Storage
Sources Useful resources and links I used to create this article
■ Full Stack Web3 with Lens Protocol, Next.js, and GraphQL ■ Lens docs ■ Bundlr docs
No activity yet