Handle for Profiles

Learn how to use Handles with Profiles.


In this page we will show you how to manage Handle-Profile relationships.

You must be authenticated with the Profile you intend to manage Handles for. See Profile Login for more information.

Typical use cases include:

  • Listing all the Handles owned by a Profile owner.

  • Linking an Handle to a Profile.

  • Unlinking an Handle from a Profile.

Owned Handles

Start by listing all Handles owned by your address.

To retrieve all the handles associated with the currently authenticated wallet, combine the useOwnedHandles hook with the ProfileSession returned by the useSession function.

Available in @lens-protocol/react-web and @lens-protocol/react-native

MyHandles.tsx
import { ProfileSession, useOwnedHandles } from '@lens-protocol/react-web';
import { HandleOption } from './HandleOption';
export function MyHandles({ session }: { session: ProfileSession }) {  const { data, loading, error, } = useOwnedHandles({    for: session.address,  });

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  if (data.length === 0) return <div>No handles found</div>;
  return (    <div>      {data.map((handle) => (        <HandleOption key={handle.id} handle={handle} />      ))}    </div>  );}

Now that you know how to list the Handles owned by your address, you can link one of them to your Profile.

When you link a Handle to a Profile, it automatically unlinks from any other Profile it might be connected to.

Building on the previous example, we'll illustrate how to use the useLinkHandle hook. This hook links a Handle to your Profile. We'll implement this within the HandleOption example component.

Available in @lens-protocol/react-web and @lens-protocol/react-native

The hook choose the Signless Experience when possible; otherwise, it will fall back to a signed experience.

HandleOption.tsx
import { HandleInfo, useLinkHandle } from '@lens-protocol/react-web';
export function HandleOption({ handle }: { handle: string }) {  const { execute, loading } = useLinkHandle();
  const link = async () => {    const result = await execute({ handle });
    // detect if an early error occurred    if (result.isFailure()) {      window.alert(result.error.message);      return;    }
    // optional: wait for the transaction to be mined and indexed    const completion = await result.value.waitForCompletion();
    // detect if a minining/indexing error occurred    if (completion.isFailure()) {      window.alert(completion.error.message);      return;    }
    // success!    window.alert(`Handle ${handle.fullHandle} linked!`);  };
  return (    <button onClick={link} disabled={loading}>      Link    </button>  );}

The process to unlink a Handle from a Profile is quite similar to the process used to link it.

Building on the previous example, we'll now add the ability to unlink a Handle from a Profile to the HandleOption component. We'll accomplish this using the useUnlinkHandle hook.

Available in @lens-protocol/react-web and @lens-protocol/react-native

The hook choose the Signless Experience when possible; otherwise, it will fall back to a signed experience.

HandleOption.tsx
import { HandleInfo, useUnlinkHandle } from '@lens-protocol/react-web';
export function HandleOption({ handle }: { handle: string }) {  const { execute: link, loading: linking } = useUnlinkHandle();  const { execute: unlink, loading: unlinking } = useUnlinkHandle();
  const linkHandle = async () => {    // omitted for brevity  };
  const unlinkHandle = async () => {    const result = await unlink({ handle });
    // detect if an early error occurred    if (result.isFailure()) {      window.alert(result.error.message);      return;    }
    // optional: wait for the transaction to be mined and indexed    const completion = await result.value.waitForCompletion();
    // detect if a minining/indexing error occurred    if (completion.isFailure()) {      window.alert(completion.error.message);      return;    }
    // success!    window.alert(`Handle ${handle.fullHandle} unlinked!`);  };
  return (    <>      <button onClick={linkHandle} disabled={linking || unlinking}>        Link      </button>
      <button onClick={unlinkHandle} disabled={linking || unlinking}>        Unlink      </button>    </>  );}

Rendering Handles

With Lens V2, the Lens platform adopted a more flexible approach to Handles. Rather than enforcing a specific format, Lens allows you to choose the format that best fits your community.

As discussed in the Concepts section, Lens Handles consist of two parts: a namespace and a local-name. We refer to this combined format as the full-handle.

Full-handleNamespaceLocal-name
lens/alicelensalice
lens/boblensbob

At present, the only supported namespaces is lens.

Integrators have the flexibility to display Handles in any format they prefer. Here are a few examples:

@alice@lens/alicelens/@alice

The Lens API facilitates flexible handle rendering by providing an object with all the necessary information. In each profile object, there's an optional handle property that contains the Handle information.

The handle property is optional because a Profile may not have a handle linked to it.

import { profileId, useProfile } from "@lens-protocol/react-web";
const { data, error, loading } = useProfile({  forProfileId: profileId("0x24"),});
// ...
console.log(data?.handle);

The Handle object is structured as follows:

{  "id": "0xb59c4ed5157c3ece17d32a61f372d035d53fd12dd0d12618cc96439a5c6a134c",  "fullHandle": "lens/alice",  "namespace": "lens",  "localName": "alice",  "suggestedFormatted": {    "full": "lens/@alice",    "localName": "@alice"  },  "linkedTo": {    "contract": {      "address": "0x5fcffF20302F3326B20052ab9C217C44F6480901",      "chainId": 137    },    "nftTokenId": "0x43"  },  "ownedBy": "0x358ba21F6ff51cf0CD4765C3Bc9fAD2030a591d6"}

In this guide, we'll focus on the following properties:

  • id: The ID of the Handle NFT.

  • fullHandle: The full handle format.

  • namespace: The namespace part of the full handle.

  • localName: The local name part of the full handle.

  • suggestedFormatted: A convenience object provided by the API with preformatted options. Use this if suits your needs.
    • full: The full handle in a mention format.

    • localName: The local name in a mention format.

Important: When querying the Lens API (directly or indirectly), anywhere a Handle is requested, it must be in its full-handle format (lens/alice). The only exception is when claiming a Handle, where you just need to provide the desired local-name. See Onboarding for more details.


That's it—you now have a solid understanding of how to manage Handle-Profile relationships.