Create an Account
This guide will help you create your first Lens account.
The process of creating a Lens Account differs slightly depending on whether you want to create a free username (such as one in the lens/ Global Namespace) or a username within a Custom Namespace that may be token-gated or require fees.
Account With Free Username
To create a new Account with a free Username, follow these steps
First, authenticate as an Onboarding User.
- TypeScript
- GraphQL
- React
Use the @lens-protocol/client package to authenticate with the user's wallet.
The process is explained in detail in the Authentication guide, so we will keep it brief here.
Then, verify if the desired username is available.
- TypeScript
- GraphQL
- React
Use the canCreateUsername action as follows:
The CanCreateUsernameResult tells you if the logged-in user satisfy the Namespace Rules for creating a username, and if the desired username is available.
Check CanCreateUsernameResult
switch (data.__typename) { case "NamespaceOperationValidationPassed": // Creating a username is allowed break;
case "NamespaceOperationValidationFailed": // Creating a username is not allowed console.log(data.reason); break;
case "NamespaceOperationValidationUnknown": // Validation outcome is unknown break;
case "UsernameTaken": // The desired username is not available break;}
Where:
NamespaceOperationValidationPassed: The logged-in user can create a username under the desired Namespace.
NamespaceOperationValidationFailed: Reposting is not allowed. The reason field explains why, and unsatisfiedRules lists the unmet requirements.
NamespaceOperationValidationUnknown: The Namespace has one or more unknown rules requiring ad-hoc verification. The extraChecksRequired field provides the addresses and configurations of these rules.
UsernameTaken: The desired username is not available.
Treat the NamespaceOperationValidationUnknown as failed unless you intend to support the specific rules. See Namespace Rules for more information.
Then, create an Account Metadata object.
The following example demonstrates the most efficient way to create Account Metadata using Grove storage.
Let's assume there is a form where the user can enter their name, bio, and a profile picture. See other Account metadata fields at the bottom of this page.
Example Form
<form onSubmit={onSubmit} id="account-form"> <label htmlFor="picture">Picture:</label> <input type="file" name="picture" accept="image/png" multiple />
<label htmlFor="name">Name:</label> <input type="text" name="name" />
<label htmlFor="bio">Bio:</label> <textarea name="bio" rows={3}></textarea>
<button type="submit">Sign Up</button></form>
Use an instance of the StorageClient to create a Grove folder containing your media files (such as a profile picture), and set the Account Metadata object as the index file.
- TypeScript
- GraphQL
- React
Then, use the createAccountWithUsername action to deploy Lens Account smart contract and contextually create a username for it.
And, handle the result using the adapter for the library of your choice and wait for it to be indexed.
See the Transaction Lifecycle guide for more information on how to determine the status of the transaction.
Finally, switch to the Account Owner authentication role to access the newly created Account.
- TypeScript
- GraphQL
- React
Use the fetchAccount action to retrieve the newly created Account, then call the SessionClient.switchAccount method to switch the authentication role to Account Owner for that Account.
Switch to Account Owner
import { nonNullable } from "@lens-protocol/client";import { fetchAccount } from "@lens-protocol/client/actions";
// …
const result = await createAccountWithUsername(sessionClient, { username: { localName: "wagmi" }, metadataUri: uri("lens://4f91ca…"),}) .andThen(handleOperationWith(walletClientOrSigner)) .andThen(sessionClient.waitForTransaction) .andThen((txHash) => fetchAccount(sessionClient, { txHash }).map(nonNullable)) .andThen((account) => sessionClient.switchAccount({ account: account.address, }), );
That's it—you are now authenticated with the newly created Account.
Account With Restricted Username
If you’re creating an Account with a username in a Namespace that enforces token gating or fees, follow these steps.
First, authenticate as an Onboarding User.
- TypeScript
- GraphQL
- React
Use the @lens-protocol/client package to authenticate with the user's wallet.
The process is explained in detail in the Authentication guide, so we will keep it brief here.
Then, verify if the desired username is available and the user's wallet satisfies the Namespace Rules.
- TypeScript
- GraphQL
- React
Use the canCreateUsername action as follows:
Verify Username Availability
import { evmAddress, RulesSubject } from "@lens-protocol/client";import { canCreateUsername } from "@lens-protocol/client/actions";
import { client } from "./client";
const result = await canCreateUsername(sessionClient, { localName: "wagmi", namespace: evmAddress("0x1234…"), rulesSubject: RulesSubject.Signer,});
if (result.isErr()) { return console.error(result.error);}
result.value; // CanCreateUsernameResult
Setting rulesSubject to signer means that the Namespace Rules will be checked against the wallet address of the currently logged-in user.
The CanCreateUsernameResult tells you if the logged-in user satisfy the Namespace Rules for creating a username, and if the desired username is available.
Check CanCreateUsernameResult
switch (data.__typename) { case "NamespaceOperationValidationPassed": // Creating a username is allowed break;
case "NamespaceOperationValidationFailed": // Creating a username is not allowed console.log(data.reason); break;
case "NamespaceOperationValidationUnknown": // Validation outcome is unknown break;
case "UsernameTaken": // The desired username is not available break;}
Where:
NamespaceOperationValidationPassed: The logged-in user can create a username under the desired Namespace.
NamespaceOperationValidationFailed: Reposting is not allowed. The reason field explains why, and unsatisfiedRules lists the unmet requirements.
NamespaceOperationValidationUnknown: The Namespace has one or more unknown rules requiring ad-hoc verification. The extraChecksRequired field provides the addresses and configurations of these rules.
UsernameTaken: The desired username is not available.
Treat the NamespaceOperationValidationUnknown as failed unless you intend to support the specific rules. See Namespace Rules for more information.
Then, create an Account Metadata object.
The following example demonstrates the most efficient way to create Account Metadata using Grove storage.
Let's assume there is a form where the user can enter their name, bio, and a profile picture. See other Account metadata fields at the bottom of this page.
Example Form
<form onSubmit={onSubmit} id="account-form"> <label htmlFor="picture">Picture:</label> <input type="file" name="picture" accept="image/png" multiple />
<label htmlFor="name">Name:</label> <input type="text" name="name" />
<label htmlFor="bio">Bio:</label> <textarea name="bio" rows={3}></textarea>
<button type="submit">Sign Up</button></form>
Use an instance of the StorageClient to create a Grove folder containing your media files (such as a profile picture), and set the Account Metadata object as the index file.
- TypeScript
- GraphQL
- React
Then, use the createAccount action to deploy Lens Account smart contract without a username (yet).
And, handle the result using the adapter for the library of your choice and wait for it to be indexed.
See the Transaction Lifecycle guide for more information on how to determine the status of the transaction.
Then, switch to the Account Owner authentication role to access the newly created Account.
- TypeScript
- GraphQL
- React
Use the fetchAccount action to retrieve the newly created Account, then call the SessionClient.switchAccount method to switch the authentication role to Account Owner for that Account.
Switch to Account Owner
import { nonNullable } from "@lens-protocol/client";import { fetchAccount } from "@lens-protocol/client/actions";
// …
const result = await createAccount(sessionClient, { metadataUri: uri("lens://4f91ca…"),}) .andThen(handleOperationWith(walletClientOrSigner)) .andThen(sessionClient.waitForTransaction) .andThen((txHash) => fetchAccount(sessionClient, { txHash }).map(nonNullable)) .andThen((account) => sessionClient.switchAccount({ account: account.address, }), );
Finally, use the createUsername action to assign a username to the newly created Account within the desired restricted Namespace.
- TypeScript
- GraphQL
- React
Use the createUsername action to create the desired username.
Restricted Namespace
import { evmAddress, RulesSubject } from "@lens-protocol/client";import { createUsername } from "@lens-protocol/client/actions";
const result = await createUsername(sessionClient, { username: { localName: "wagmi", namespace: evmAddress("0x1234…"), }, rulesSubject: RulesSubject.Signer,});
And, handle the result using the adapter for the library of your choice and wait for it to be indexed.
See the Transaction Lifecycle guide for more information on how to determine the status of the transaction.
Setting rulesSubject to signer means that the Namespace Rules will be checked against the wallet address of the currently logged-in user.
That's it—you are now authenticated with the newly created Account and have a username in a restricted Namespace.
Advanced Options
Account Metadata Fields
Account Metadata object is a JSON object that contains information about the Account, such as its name, bio, profile picture, and other attributes. It is used to display the Account's information in the Lens ecosystem.
- TS/JS
- JSON Schema
Use the @lens-protocol/metadata package to construct a valid AccountMetadata object:
Example
import { MetadataAttributeType, account } from "@lens-protocol/metadata";
const metadata = account({ name: "Jane Doe", bio: "I am a photographer based in New York City.", picture: "lens://4f91cab87ab5e4f5066f878b72…", coverPicture: "lens://4f91cab87ab5e4f5066f8…", attributes: [ { key: "twitter", type: MetadataAttributeType.STRING, value: "https://twitter.com/janedoexyz", }, { key: "dob", type: MetadataAttributeType.DATE, value: "1990-01-01T00:00:00Z", }, { key: "enabled", type: MetadataAttributeType.BOOLEAN, value: "true", }, { key: "height", type: MetadataAttributeType.NUMBER, value: "1.65", }, { key: "settings", type: MetadataAttributeType.JSON, value: '{"theme": "dark"}', }, ],});
See the Lens Metadata Standards guide for more information on creating and hosting Metadata objects.