Lens Profile Manager
Previously known as "Dispatcher".
The Profile Manager enables gasless and signless transactions (transactions without signing any approval modals) in your Lens app.
Blockchain technology introduced many drawbacks like wallet popups, seed phrases, passwords, funds, and multi-network (blockchain) dynamics. These are fundamental for securing cryptographic transactions but present many UX challenges. So, are we doomed, or should we be optimistic?
In blockchain terms, Optimistic means that we assume the transaction will come through so we don't need to wait for validators to reach a consensus. This wouldn't be acceptable for financial transactions because of the double spending problem but can be helpful for social media interactions.
Social media is about great frontend experiences so having wallet prompts for every share or follow is not ideal. The challenge is that being optimistic in a front-end experience is possible but still, every action must be approved by the user wallet.
To solve this issue, we created the Profile Manager. Basically, it is an intermediate wallet with funds that act as the signer for every transaction. We only have to delegate signing privileges to this profile manager wallet which operates hidden in the backend. This combined with an optimistic UI creates a seamless experience identical to what we are used to today.
What The Profile Manager Can Be Used For
The profile manager works for creating posts, comments & mirrors and updating profile metadata.
As the profile manager can only use a subset of methods this doesn't mean you can not be gasless for everything. Any withSig
methods at the contract level are able to be used by the profile manager.
Profile Manager Examples
Check If a Profile Has The Profile Manager Enabled
The profile manager is something that each profile can opt-in to. So before trying to execute any transactions via the Profile Manager, you should check whether the profile has the functionality enabled.
You can do this by using the signless
property available on each Profile
.
Important to know
signless
is only populated for the currently logged in profile, for all others profile it's always set tonull
.
Invocation
const profile = await lensClient.profile.fetch({
profileId: YOUR_PROFILE_ID,
});
if (profile?.signless) {
console.log('Profile manager is enabled');
} else {
console.log('Profile manager is disabled');
}
query Profile {
profile(request: { forProfileId: "0x18" }) {
signless
}
}
Response
If the signless
boolean flag is set to true, this means they can use the built-in profile manager on the API.
Note: Profiles could have been mapped to another profile manager outside of the Lens API. If so, signless
will be false and you will not be able to execute profile manager transactions for this profile.
Enabled/Disable Profile Manager
This request is protected by authentication
hint: this means it requires an x-access-token header put in the request with your authentication token.
This API call allows you to get the typed data to then call the withSig
method to set a profile manager for your Lens profile.
Profile manager allows another address to post, comment, mirror, set follow module and change the profile picture on behalf of you using their wallet
Typed data is a way to try to show the users what they are signing in a more readable format. You can read more about it here.
Constructing that type of data is normally difficult. On the type data, you also need to get the nonce, deadline, contract version, contract address, chain id, and the name of the contract for the signature to be able to be signed and verified.
When using this API the server checks every detail before it generates the typed data. For example: if you try to create typed data on an always failing transaction the server will throw an error in a human-readable form. This is great for debugging but also saves issues with users sending always failing transactions or a mismatch of a bad request.
We will show you the typed data approach using ethers and the API side by side. Keep in mind that with the typed data approach you use the withSig
methods which can be called by you with your signature or with that signature any relay could call it for you on your behalf allowing gasless transactions.
Parameters
- approveSignless:
boolean
(required)- Flag to determine whether the Lens Profile Manager is enabled or not.
- changeManagers :
ChangeProfileManager[]
(required)address
:EvmAddress
- The address of the profile manager
action
:ChangeProfileManagerActionType
- Either
ChangeProfileManagerActionType.ADD
to add a new profile manager orChangeProfileManagerActionType.REMOVE
to remove
- Either
Invocation
const typedDataResult = await lensClient.profile.createChangeProfileManagersTypedData({
approveSignless: true, // or false to disable
// leave blank if you want to use the lens API dispatcher!
// changeManagers: [
// {
// action: ChangeProfileManagerActionType.Add,
// address: '0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF',
// },
// ],
});
mutation CreateChangeProfileManagersTypedData(
$request: ChangeProfileManagersRequest!
$options: TypedDataOptions
) {
createChangeProfileManagersTypedData(request: $request, options: $options) {
id
expiresAt
typedData {
types {
ChangeDelegatedExecutorsConfigWithSig {
name
type
}
}
domain {
__typename
name
chainId
version
verifyingContract
}
value {
nonce
deadline
}
}
}
}
Response
The response is the typed data object for changing profile manager for a profile, you must then broadcast this onchain using Broadcast Onchain Transaction.
Full LensClient Example
const typedDataResult = await lensClient.profile.createChangeProfileManagersTypedData({
approveSignless: true,
changeManagers: [
{
action: ChangeProfileManagerActionType.Add,
address: "0x0000000000",
},
],
});
const { id, typedData } = typedDataResult.unwrap();
// sign with the wallet
const signedTypedData = await wallet._signTypedData(
typedData.domain,
typedData.types,
typedData.value
);
// broadcast onchain
const broadcastOnchainResult = await lensClient.transaction.broadcastOnchain({
id,
signature: signedTypedData,
});
const onchainRelayResult = broadcastOnchainResult.unwrap();
if (onchainRelayResult.__typename === "RelayError") {
console.log(`Something went wrong`);
return;
}
console.log(
`Successfully changed profile managers with transaction with id ${onchainRelayResult}, txHash: ${onchainRelayResult.txHash}`
);
Full GraphQL API Example
Enable / Disable Profile Manager GraphQL API examples
Hooking in without using the type data
You may not want to go down the typed data with the signature route and just send the transaction directly from the client to the blockchain without any API call to map the data for you. You will need to do the encoding and validation yourself if you go down that approach. This is out of scope for the API documentation as would have been explained and showed how to do it in the contract docs. This tries to advise the same practice as what seaport
on OpenSea are doing alongside a lot of other projects which tries to improve the visibility of what the user is signing.
Our profile manager resolver contains:
Updated 5 months ago