Guides

Set Follow Module

🚧

This Request is Protected by Authentication

hint: this means it requires an x-access-token header put in the request with your authentication token.

📘

Lens Profile Manager Compatible: Gasless & Signless

This action can be used through the Lens Profile Manager to enable a gasless and signless experience.

Set a profile's follow module that allows for different sets of conditions to be applied to how that profile can be followed.

There are three different approaches you can use to set a profile's follow module. Depending on the whitelist status of your app and the settings of the profile you would like to follow from, you can use:

  • a) Set Follow Module via Lens Profile Manager (Gasless & Signless)
  • b) Set Follow Module Using TypedData and Broadcasting Onchain via the API (Gasless & Signed)
  • c) Set Follow Module Using TypedData and Calling The Contract Directly (Self-funded Gas & Signed)

To decide which approach to use, you can use the following table. Please note that a profile may also have another Profile Manager enabled that is not powered by the Lens API, this is not covered below. To learn more about checking a profile's Profile Manager settings, see Profile Manager.

Is Your App Whitelisted?Profile has Lens Profiles Manager Enabled?Approach To Use
1truetrueLens Profile Manager
2truefalseTypedData & Broadcast via API
3falsetrueTypedData & Self-Funded
4falsefalseTypedData & Self-Funded

a) Set Follow Module via Lens Profile Manager

If possible, using the Lens Profile Manager is the best way to set a profile's follow module. This will be a gasles and signless operation.

Request

  • followModule: FollowModuleInput (required)

Invocation

const result = await lensClient.profile.setFollowModule({
  followModule: {
    freeFollowModule: true,
  },
});
mutation SetFollowModule {
  result: setFollowModule(
    request: { followModule: { freeFollowModule: true } }
  ) {
    ... on RelaySuccess {
      ...RelaySuccess
    }
    ... on LensProfileManagerRelayError {
      ...LensProfileManagerRelayError
    }
  }
}

Response

{
  "txHash": "0x000000",
  "txId": "0x01"
}
{
  "reason": "FAILED" // LensProfileManagerRelayErrorReasonType
}

b) Set Follow Module Using TypedData and Broadcasting Onchain via the API

Request

  • followModule: FollowModuleInput (required)

Invocation

const result = await lensClient.profile.createSetFollowModuleTypedData({
  followModule: {
    freeFollowModule: true,
  },
});
mutation CreateSetFollowModuleTypedData {
  result: createSetFollowModuleTypedData(
    request: { followModule: { freeFollowModule: true } }
  ) {
    ...CreateSetFollowModuleBroadcastItemResult
  }
}

Response

{
  "id": "0x01",
  "expiresAt": "2023-10-01T00:00:00Z",
  "typedData": {
    "types": {
      "SetFollowModule": [
        { "name": "...", "type": "..." },
        { "name": "...", "type": "..." }
      ]
    },
    "domain": {
      "name": "...",
      "chainId": "...",
      "version": "...",
      "verifyingContract": "0x0000000"
    },
    "value": {
      "nonce": "...",
      "deadline": "2023-10-01T01:00:00Z"
    }
  }
}

Broadcasting the TypedData

Once you have the typed data for the follow action, you need to get the user to sign with their wallet and then broadcast it onchain.

See Broadcasting Onchain for more information.


Building Different Follow Module Requests

Free Follow Module Request

No restrictions or cost to follow the profile.

{
  "followModule": {
    "freeFollowModule": true
  }
}

Fee Follow Module Request

The profile charges a fee in order to follow them.

To set the fee follow module you need to pass in:

  • currency: the contract address of the currency you want to be paid in
  • value: the amount of the currency you want to be paid
  • recipient: the address you want the funds to be sent to

The value should be passed in as the normal amount, there is no need to shift to the decimal places, the Lens API handles this.

{
  "followModule": {
    "feeFollowModule": {
      "amount": {
        "currency": "0xD40282e050723Ae26Aeb0F77022dB14470f4e011",
        "value": "0.01"
      },
      "recipient": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF"
    }
  }
}

Revert Follow Module Request

The profile cannot be followed.

{
  "followModule": {
    "revertFollowModule": true
  }
}

Unknown Follow Module Request

The profile has an unknown follow module set.

{
  "followModule": {
    "unknownFollowModule": {
      "address": "0x000",
      "data": "..."
    }
  }
}

c) Set Follow Module Using TypedData and Calling The Contract Directly (Self-funded Gas & Signed)

If your app is not whitelisted, you can still use the Lens API to generate the typed data for you to sign and broadcast to the contract yourself.

You can also opt to bypass the API completely, compose your own typed data in your client and call the contract directly. In this case, you'll be responsible for all encoding and validation.

This approach isn't covered in the API documentation, you can find guidance in the contract documentation.


Full LensClient Example

Using the Lens Profile Manager:

// your LensClient instance must be authenticated

const result = await lensClient.profile.setFollowModule({
  followModule: {
    freeFollowModule: true,
  },
});

// example request for each follow module

// const result = await lensClient.profile.setFollowModule({
//   followModule: {
//     feeFollowModule: {
//       amount: {
//         currency: "MATIC",
//         value: "0.01",
//       },
//       recipient: "0x0000000",
//     },
//   },
// });

// const result = await lensClient.profile.setFollowModule({
//   followModule: {
//     revertFollowModule: true,
//   },
// });

// const result = await lensClient.profile.setFollowModule({
//   followModule: {
//     unknownFollowModule: {
//       address: "0x0000000",
//       data: "0x0000000",
//     },
//   },
// });

const followModuleResultValue = result.unwrap();

if (!isSuccessfulLensProfileManagerResponse(followModuleResultValue)) {
  throw new Error("Failed to set follow module");
}

await lensClient.transaction.waitUntilComplete({
  txId: followModuleResultValue.txId,
});

Using TypedData and Broadcasting Onchain:

// your LensClient instance must be authenticated

const setFollowModuleTypedDataResult =
  await lensClient.profile.createSetFollowModuleTypedData({
    followModule: {
      freeFollowModule: true,
    },
  });

// const setFollowModuleTypedDataResult = await lensClient.profile.createSetFollowModuleTypedData({
//   followModule: {
//     feeFollowModule: {
//       amount: {
//         currency: "MATIC",
//         value: "0.01",
//       },
//       recipient: "0x0000000",
//     },
//   },
// });

// const setFollowModuleTypedDataResult = await lensClient.profile.createSetFollowModuleTypedData({
//   followModule: {
//     revertFollowModule: true,
//   },
// });

// const setFollowModuleTypedDataResult = await lensClient.profile.createSetFollowModuleTypedData({
//   followModule: {
//     unknownFollowModule: {
//       address: "0x0000000",
//       data: "0x0000000",
//     },
//   },
// });

const data = setFollowModuleTypedDataResult.unwrap();

const signedTypedData = await wallet._signTypedData(
  data.typedData.domain,
  data.typedData.types,
  data.typedData.value
);

const broadcastResult = await lensClient.transaction.broadcastOnchain({
  id: data.id,
  signature: signedTypedData,
});

const followBroadcastResultValue = broadcastResult.unwrap();

if (!isRelaySuccess(followBroadcastResultValue)) {
  console.log(`Something went wrong`, followBroadcastResultValue);
  return;
}

console.log(
  `Profile follow module sucessfully set and successfully broadcasted with txId ${followBroadcastResultValue.txId}`
);

// wait for follow to be indexed
await lensClient.transaction.waitUntilComplete({
  txId: followBroadcastResultValue.txId,
});

Full GraphQL API Example

📘

Set Follow Module: GraphQL API Full Example