Module Metadata

Learn how to document your Custom Module.


Lens module authors have the ability to attach a collection of information to their modules. This information serves to:

  • Inform integrators about the capabilities of the module

  • Provide guidance to consumers on how to integrate the module

Metadata Standard

The TypeScript definition for the Module Metadata is available here, and it's also provided below for your convenience.

type ModuleMetadata = {  /**   * The name of the module.   */  name: string;  /**   * The human-friendly title for the module.   */  title: string;  /**   * Markdown formatted description of the module.   *   * It should explain what this module does, how to use it, examples just   * like you would if you were building an NPM package.   * The more detail the better to allow dApp to easily integrate it.   */  description: Markdown;  /**   * List of authors email addresses.   */  authors: string[];  /**   * The Solidity JSON ABI as JSON-string describing the initialization   * function calldata.   *   * This will be used to encode the calldata for the initialization function.   *   * It will also be used by the consumers of this module to decode the   * initialization calldata so to infer the initialization criteria.   */  initializeCalldataABI: string;  /**   * The Solidity JSON ABI as JSON-string describing the initialization   * result data.   *   * This will be used by the consumers of this module to decode   * the result data from the initialization function so to infer the   * initialization result state.   */  initializeResultDataABI?: string;  /**   * The Solidity JSON ABI as JSON-string describing the process   * function calldata.   *   * This will be used to encode the calldata for the process function.   *   * Some modules might non need to return any initialization result data.   */  processCalldataABI: string;  /**   * An arbitrary bag of attributes you wish to add to the metadata.   */  attributes: MetadataAttribute[];  /**   * The schema ID.   */  $schema: ModuleSchemaId.LATEST;};

To generate Module Metadata, follow these steps:

  1. Create a Module Metadata object.

  2. Upload the created Module Metadata object to a public URI.

  3. Link the Module Metadata URI with your module contract.

1

Create Module Metadata

Module Metadata objects must conform to the structure defined by the Module Metadata Standard. This is a self-describing specification, meaning the data itself contains all the information required for its validation.

You can construct Module Metadata objects in two ways:

  • By utilizing the @lens-protocol/metadata package

  • Manually, with the help of a dedicated JSON Schema

To get started, install the @lens-protocol/metadata package along with its necessary peer dependencies:

npm install zod @lens-protocol/metadata@latest

Use the module function to build a valid ModuleMetadata object:

Example
import { module } from '@lens-protocol/metadata';
const metadata = module({  name: 'My Open Action',  title: 'This is my Open Action',  description: 'Get ready for the future of social interaction!',  authors: ['[email protected]'],  initializeCalldataABI: JSON.stringify([    {      type: 'address',      name: 'address',    },    {      type: 'uint256',      name: 'price',    },  ]),  processCalldataABI: JSON.stringify([    {      type: 'address',      name: 'collector',    },  ]),});

This function validates the metadata contextually, preparing it to be uploaded as JSON to a public URI of your choice.

2

Upload Metadata

You can host Module Metadata anywhere, as long as it's publicly accessible via a URI and served with the appropriate Content-Type: application/json header.

Commonly, integrators use solutions like IPFS or Arweave for hosting metadata objects.

3

In your Module contract, you can associate the Module Metadata by returning its URI from the getModuleMetadataURI function.

function getModuleMetadataURI() external view returns (string memory)

The Lens backend invokes this function when the module is registered.


Additional Options

Retrieve Module Metadata

If you've identified a module of interest and have its EVM address, you can retrieve its metadata along with valuable information from its verification process (see Verified Modules).

This information includes:

  • moduleType: The type of the module, which can be either FOLLOW, OPEN_ACTION, or REFERENCE.

  • signlessApproved: Indicates whether the module is enabled to be executed within a Signless Experience.

  • sponsoredApproved: Indicates whether the module can be executed as part of a Sponsored Transaction.

  • verified: Indicates whether the module has been verified by the Lens Protocol team. See Verified Modules for more information.

  • metadata: Contains the information that the author provided via the Module Metadata object.

The useModuleMetadata hook can be used to retrieve the metadata of any registered module.

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

ModuleMetadata.tsx
import { useModuleMetadata } from '@lens-protocol/react-web';
function ModuleMetadata({ address }: { address: string }) {  const { data, loading, error } = useModuleMetadata({    implementation: '0x83E5aA2E3f46D3fad010d2cbC5F6Cb90Ec440aA5',  });
  if (loading) {    return <div>Loading...</div>;  }
  if (error) {    return <div>Error: {error.message}</div>;  }
  if (!data) {    return <div>Module not found</div>;  }
  return (    <div>      <h1>{data.metadata.title}</h1>      <p>{data.metadata.description}</p>
      <p>Created by: {data.metadata.authors}</p>
      <ul>        <li>Type: {data.type}</li>        <li>Lens Team verified: {data.verified}</li>        <li>Signless Approved: {data.signlessApproved}</li>        <li>Sponsored Approved: {data.sponsoredApproved}</li>      </ul>    </div>  );}

Alternatively, you can use the useLazyModuleMetadata hook, which retrieves the metadata only when necessary.

import { useLazyModuleMetadata, NotFoundError } from '@lens-protocol/react-web';
// ...
const { execute } = useLazyModuleMetadata();
// ... in an async functionconst result = await execute({  implementation: '0x83E5aA2E3f46D3fad010d2cbC5F6Cb90Ec440aA5',});
if (result.isFailure()) {  // result.error instance of NotFoundError or UnspecifiedError  console.error(result.error.message);  return}
// result.value is a ModuleMetadataResultconsole.log(result.value)

Update Module Metadata

If your Module Metadata can change (for example, if you use a dynamic setter/getter approach in your module), you'll need to trigger a metadata refresh in the ModuleRegistry.

This is a straightforward process that involves calling the following function:

ModuleRegistry.emitModuleMetadataRefresh(address moduleAddress)

This function is public, so anyone can trigger it.

Please note that the module must already be registered before you can call this function.