Skip to content

Commit af5dcbf

Browse files
committed
feat: Lens V3 frame client (WIP)
1 parent b2674c4 commit af5dcbf

File tree

1 file changed

+88
-96
lines changed

1 file changed

+88
-96
lines changed

packages/render/src/identity/lens/use-lens-identity.tsx

Lines changed: 88 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import {
77
useSignMessage,
88
useSwitchChain,
99
} from "wagmi";
10-
import { LensClient, development, production } from "@lens-protocol/client";
10+
import { PublicClient, testnet } from "@lens-protocol/client";
11+
import { signFrameAction, createFrameTypedData, fetchAccountManagers } from "@lens-protocol/client/actions";
1112
import type {
1213
SignerStateActionContext,
1314
SignerStateInstance,
@@ -17,33 +18,34 @@ import type { Storage } from "../types";
1718
import { WebStorage } from "../storage";
1819
import { useFreshRef } from "../../hooks/use-fresh-ref";
1920
import type { LensFrameContext } from "./use-lens-context";
21+
import { fetchAccountsAvailable } from "@lens-protocol/client/actions";
2022

2123
export type LensProfile = {
22-
id: string;
23-
handle?: string;
24+
account: string;
25+
username: string;
2426
};
2527

2628
export type LensSigner = {
27-
profileId: string;
29+
account: string;
2830
accessToken: string;
2931
identityToken: string;
30-
handle: string;
31-
address: `0x${string}`;
32+
username: string;
3233
};
3334

3435
type LensFrameRequest = {
3536
clientProtocol: string;
3637
untrustedData: {
3738
specVersion: string;
38-
profileId: string;
39-
pubId: string;
39+
account: string;
40+
post: string;
41+
app: string;
4042
url: string;
4143
buttonIndex: number;
4244
unixTimestamp: number;
4345
deadline?: number;
4446
inputText?: string;
4547
state?: string;
46-
actionResponse?: string;
48+
transactionId?: string;
4749
identityToken: string;
4850
};
4951
trustedData: {
@@ -79,6 +81,9 @@ type LensIdentityOptions = {
7981

8082
const defaultStorage = new WebStorage();
8183

84+
// Testnet app address (demo)
85+
const TESTNET_APP_ADDRESS = "0xaC19aa2402b3AC3f9Fe471D4783EC68595432465";
86+
8287
export function useLensIdentity({
8388
storage = defaultStorage,
8489
storageKey = "lensProfile",
@@ -99,11 +104,10 @@ export function useLensIdentity({
99104
const storageKeyRef = useFreshRef(storageKey);
100105
const addressRef = useFreshRef(address);
101106

102-
const lensClient = useRef(
103-
new LensClient({
104-
environment: environment === "development" ? development : production,
105-
})
106-
).current;
107+
const lensClient = PublicClient.create({
108+
environment: testnet,
109+
storage: window.localStorage,
110+
});
107111

108112
const connectRef = useFreshRef(connect);
109113

@@ -130,70 +134,50 @@ export function useLensIdentity({
130134
async (profile: LensProfile) => {
131135
try {
132136
const walletAddress = addressRef.current;
133-
134137
if (!walletAddress) {
135138
throw new Error("No wallet connected");
136139
}
137-
138140
setShowProfileSelector(false);
139141

140-
const { id, text } = await lensClient.authentication.generateChallenge({
141-
signedBy: walletAddress,
142-
for: profile.id,
143-
});
144-
const signature = await signMessageAsync({
145-
message: {
146-
raw:
147-
typeof text === "string"
148-
? Buffer.from(text)
149-
: Buffer.from(text as Uint8Array),
142+
const authenticated = await lensClient.login({
143+
accountOwner: {
144+
account: profile.account,
145+
app: TESTNET_APP_ADDRESS,
146+
owner: walletAddress,
147+
},
148+
signMessage: async (message: string) => {
149+
const signature = await signMessageAsync({
150+
message: { raw: Buffer.from(message) },
151+
});
152+
return signature;
150153
},
151154
});
152155

153-
await lensClient.authentication.authenticate({ id, signature });
154-
155-
const accessTokenResult =
156-
await lensClient.authentication.getAccessToken();
157-
const identityTokenResult =
158-
await lensClient.authentication.getIdentityToken();
159-
const accessToken = accessTokenResult.unwrap();
160-
const identityToken = identityTokenResult.unwrap();
161-
const profileId = await lensClient.authentication.getProfileId();
162-
const profileInfo = await lensClient.profile.fetch({
163-
forProfileId: profileId,
164-
});
165-
const handle = profileInfo?.handle?.localName
166-
? `${profileInfo.handle.localName}.lens`
167-
: "";
168-
169-
if (profileId) {
170-
const signer: LensSigner = {
171-
accessToken,
172-
profileId,
173-
address: walletAddress,
174-
identityToken,
175-
handle,
176-
};
177-
178-
await storageRef.current.set<LensSigner>(
179-
storageKeyRef.current,
180-
() => signer
181-
);
182-
183-
setLensSigner(signer);
156+
if (authenticated.isErr()) {
157+
throw new Error("Authentication failed: " + authenticated.error);
184158
}
159+
160+
const sessionClient = authenticated.value;
161+
162+
const signer: LensSigner = {
163+
account: profile.account,
164+
accessToken: sessionClient.accessToken,
165+
identityToken: sessionClient.idToken,
166+
username: profile.username,
167+
};
168+
169+
await storageRef.current.set<LensSigner>(
170+
storageKeyRef.current,
171+
() => signer
172+
);
173+
174+
setLensSigner(signer);
185175
} catch (error) {
186176
// eslint-disable-next-line no-console -- provide feedback
187177
console.error("@frames.js/render: Create Lens signer failed", error);
188178
}
189179
},
190-
[
191-
addressRef,
192-
lensClient.authentication,
193-
lensClient.profile,
194-
signMessageAsync,
195-
storageKeyRef,
196-
]
180+
[addressRef, lensClient, signMessageAsync, storageKeyRef]
197181
);
198182

199183
const onSignerlessFramePress = useCallback(async () => {
@@ -212,23 +196,33 @@ export function useLensIdentity({
212196
return;
213197
}
214198

215-
const managedProfiles = await lensClient.wallet.profilesManaged({
216-
for: currentAddress,
199+
const managedProfiles = await fetchAccountsAvailable(lensClient, {
200+
managedBy: currentAddress,
201+
includeOwned: true,
217202
});
218-
const profiles: LensProfile[] = managedProfiles.items.map((p) => ({
219-
id: p.id,
220-
handle: p.handle ? `${p.handle.localName}.lens` : undefined,
221-
}));
222-
223-
if (!profiles[0]) {
224-
throw new Error("No Lens profiles managed by connected address");
225-
}
203+
if (managedProfiles.isOk()) {
204+
const profiles = managedProfiles.value.items.map((p) => ({
205+
account: p.account.address,
206+
username: p.account.username
207+
? `${p.account.username}`
208+
: p.account.address,
209+
}));
210+
211+
if (!profiles[0]) {
212+
throw new Error("No Lens profiles managed by connected address");
213+
}
226214

227-
if (managedProfiles.items.length > 1) {
228-
setAvailableProfiles(profiles);
229-
setShowProfileSelector(true);
215+
if (managedProfiles.value.items.length > 1) {
216+
setAvailableProfiles(profiles);
217+
setShowProfileSelector(true);
218+
} else {
219+
await handleSelectProfile(profiles[0]);
220+
}
230221
} else {
231-
await handleSelectProfile(profiles[0]);
222+
console.error(
223+
"@frames.js/render: Create Lens signer failed",
224+
managedProfiles.error
225+
);
232226
}
233227
} catch (error) {
234228
// eslint-disable-next-line no-console -- provide feedback
@@ -240,13 +234,13 @@ export function useLensIdentity({
240234
addressRef,
241235
connectRef,
242236
handleSelectProfile,
243-
lensClient.wallet,
244237
lensSignerRef,
238+
lensClient,
245239
]);
246240

247241
const activeConnectionRef = useFreshRef(activeConnection);
248242

249-
const signFrameAction: SignFrameActionFunction<
243+
const signLensFrameAction: SignFrameActionFunction<
250244
SignerStateActionContext<LensSigner, LensFrameContext>,
251245
LensFrameRequest
252246
> = useCallback(
@@ -257,23 +251,22 @@ export function useLensIdentity({
257251
throw new Error("No lens signer active");
258252
}
259253

260-
const profileManagers = await lensClient.profile.managers({
261-
for: signer.profileId,
262-
});
254+
const profileManagers = await fetchAccountManagers(lensClient);
263255
const lensManagerEnabled = profileManagers.items.some(
264256
(manager) => manager.isLensManager
265257
);
266258

267259
if (lensManagerEnabled) {
268-
const result = await lensClient.frames.signFrameAction({
260+
const result = await signFrameAction(lensClient, {
269261
url: actionContext.url,
270262
inputText: actionContext.inputText || "",
271263
state: actionContext.state || "",
272264
buttonIndex: actionContext.buttonIndex,
273-
actionResponse:
265+
transactionId:
274266
actionContext.type === "tx-post" ? actionContext.transactionId : "",
275-
profileId: signer.profileId,
276-
pubId: actionContext.frameContext.pubId || "",
267+
account: signer.account,
268+
app: TESTNET_APP_ADDRESS,
269+
post: actionContext.frameContext.pubId || "",
277270
specVersion: "1.0.0",
278271
});
279272

@@ -306,16 +299,17 @@ export function useLensIdentity({
306299
};
307300
}
308301

309-
const typedData = await lensClient.frames.createFrameTypedData({
302+
const typedData = await createFrameTypedData(lensClient, {
310303
url: actionContext.url,
311304
inputText: actionContext.inputText || "",
312305
state: actionContext.state || "",
313306
buttonIndex: actionContext.buttonIndex,
314-
actionResponse:
307+
transactionId:
315308
actionContext.type === "tx-post" ? actionContext.transactionId : "",
316-
profileId: signer.profileId,
317-
pubId: actionContext.frameContext.pubId || "",
318-
specVersion: "1.0.0",
309+
account: signer.account,
310+
post: actionContext.frameContext.pubId || "",
311+
app: TESTNET_APP_ADDRESS,
312+
specVersion: "1.1.0",
319313
deadline: Math.floor(Date.now() / 1000) + 86400, // 1 day
320314
});
321315

@@ -346,7 +340,7 @@ export function useLensIdentity({
346340

347341
return {
348342
body: {
349-
clientProtocol: "lens@1.0.0",
343+
clientProtocol: "lens@1.1.0",
350344
untrustedData: {
351345
...typedData.value,
352346
identityToken: signer.identityToken,
@@ -361,8 +355,6 @@ export function useLensIdentity({
361355
},
362356
[
363357
activeConnectionRef,
364-
lensClient.frames,
365-
lensClient.profile,
366358
lensSignerRef,
367359
signTypedDataAsync,
368360
switchChainAsync,
@@ -392,7 +384,7 @@ export function useLensIdentity({
392384
get hasSigner() {
393385
return !!lensSignerRef.current?.accessToken;
394386
},
395-
signFrameAction,
387+
signFrameAction: signLensFrameAction,
396388
get isLoadingSigner() {
397389
return isLoadingRef.current;
398390
},

0 commit comments

Comments
 (0)