lens-convex-auth 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -281,6 +281,7 @@ Omit the `convex` prop. Everything else works the same.
281
281
  | `lensChainRpcUrl` | thirdweb's RPC | Lens Chain RPC URL for thirdweb |
282
282
  | `storagePrefix` | `"lens_"` | Prefix of the localStorage keys the session is stored under |
283
283
  | `convexTokenEndpoint` | `"/api/convex-token"` | Where the token route lives |
284
+ | `usernameNamespace` | global Lens namespace | Namespace (0x…) new accounts get their username in. The account list shows usernames from it first, then the global one, then any other |
284
285
 
285
286
  Returns `auth` with `thirdwebClient`, `chain`, `lensClient`, `tokens`, `getSession()`,
286
287
  `resumeSession()`, `requestChallenge()`, `authenticate()`, `logout()`, `fetch()` and `fetchConvexToken()`.
@@ -53,6 +53,11 @@ type LensAuthOptions = {
53
53
  storagePrefix?: string;
54
54
  /** Route that exchanges a Lens ID token for a Convex token. Defaults to "/api/convex-token". */
55
55
  convexTokenEndpoint?: string;
56
+ /**
57
+ * Username namespace (0x…) new accounts get their username in, and whose usernames are shown first.
58
+ * Defaults to the global Lens namespace.
59
+ */
60
+ usernameNamespace?: string;
56
61
  };
57
62
  type LensLoginRole = "ACCOUNT_OWNER" | "ACCOUNT_MANAGER";
58
63
  type LensChallenge = {
@@ -76,6 +81,7 @@ declare function signLensChallenge(challenge: LensChallenge, signer: MessageSign
76
81
  declare function createLensAuth(options: LensAuthOptions): {
77
82
  environment: LensEnvironmentName;
78
83
  appAddress: string;
84
+ usernameNamespace: string | undefined;
79
85
  storagePrefix: string;
80
86
  thirdwebClient: ThirdwebClient;
81
87
  chain: Readonly<thirdweb_chains.ChainOptions & {
@@ -302,10 +302,14 @@ function createLensAuth(options) {
302
302
  if (!ADDRESS_RE.test(options.lensAppAddress ?? "")) {
303
303
  throw new Error("lens-convex-auth: lensAppAddress must be your Lens app address (0x\u2026)");
304
304
  }
305
+ if (options.usernameNamespace !== void 0 && !ADDRESS_RE.test(options.usernameNamespace)) {
306
+ throw new Error("lens-convex-auth: usernameNamespace must be a Lens namespace address (0x\u2026)");
307
+ }
305
308
  const environment = options.environment ?? "mainnet";
306
309
  const storagePrefix = options.storagePrefix ?? "lens_";
307
310
  const appAddress = options.lensAppAddress;
308
311
  const convexTokenEndpoint = options.convexTokenEndpoint ?? DEFAULT_CONVEX_TOKEN_ENDPOINT;
312
+ const usernameNamespace = options.usernameNamespace;
309
313
  const tokens = new TokenService({ storagePrefix, graphqlUrl: `${lensApiOrigin(environment)}/graphql` });
310
314
  const thirdwebClient = createThirdwebClient({ clientId: options.thirdwebClientId });
311
315
  const chain = lensThirdwebChain(environment, options.lensChainRpcUrl);
@@ -370,6 +374,7 @@ function createLensAuth(options) {
370
374
  return {
371
375
  environment,
372
376
  appAddress,
377
+ usernameNamespace,
373
378
  storagePrefix,
374
379
  thirdwebClient,
375
380
  chain,
@@ -389,8 +394,8 @@ function createLensAuth(options) {
389
394
  }
390
395
 
391
396
  // src/core/onboarding.ts
392
- import { PublicClient as PublicClient2, evmAddress as evmAddress2, signatureFrom as signatureFrom2, uri } from "@lens-protocol/client";
393
- import { canCreateUsername, createAccountWithUsername, fetchAccount, fetchUsername } from "@lens-protocol/client/actions";
397
+ import { PageSize, PublicClient as PublicClient2, evmAddress as evmAddress2, signatureFrom as signatureFrom2, uri } from "@lens-protocol/client";
398
+ import { canCreateUsername, createAccountWithUsername, fetchAccount, fetchUsername, fetchUsernames } from "@lens-protocol/client/actions";
394
399
  import { handleOperationWith } from "@lens-protocol/client/viem";
395
400
  import { account as accountMetadata } from "@lens-protocol/metadata";
396
401
  import { StorageClient, immutable } from "@lens-chain/storage-client";
@@ -420,16 +425,19 @@ function usernameFormatError(localName) {
420
425
  if (!USERNAME_PATTERN.test(localName)) return "Use only lowercase letters, numbers, - and _";
421
426
  return null;
422
427
  }
428
+ function usernameInput(auth, localName) {
429
+ return auth.usernameNamespace ? { localName, namespace: evmAddress2(auth.usernameNamespace) } : { localName };
430
+ }
423
431
  async function isUsernameTaken(auth, localName) {
424
- const result = await fetchUsername(auth.lensClient, { username: { localName } });
432
+ const result = await fetchUsername(auth.lensClient, { username: usernameInput(auth, localName) });
425
433
  if (result.isErr()) throw result.error;
426
434
  return result.value !== null;
427
435
  }
428
436
  function validationFailedMessage(failed) {
429
437
  return failed.unsatisfiedRules?.required[0]?.message || failed.reason;
430
438
  }
431
- async function checkUsername(session, localName) {
432
- const result = await canCreateUsername(session, { localName });
439
+ async function checkUsername(auth, session, localName) {
440
+ const result = await canCreateUsername(session, usernameInput(auth, localName));
433
441
  if (result.isErr()) throw result.error;
434
442
  switch (result.value.__typename) {
435
443
  case "NamespaceOperationValidationPassed":
@@ -459,7 +467,7 @@ var ACCOUNT_POLL_ATTEMPTS = 15;
459
467
  var ACCOUNT_POLL_INTERVAL_MS = 2e3;
460
468
  async function createLensAccount(auth, session, wallet, request) {
461
469
  const created = await createAccountWithUsername(session, {
462
- username: { localName: request.localName },
470
+ username: usernameInput(auth, request.localName),
463
471
  metadataUri: uri(request.metadataUri)
464
472
  });
465
473
  if (created.isErr()) throw created.error;
@@ -488,6 +496,24 @@ async function createLensAccount(auth, session, wallet, request) {
488
496
  }
489
497
  throw new OnboardingError("Your account was created but isn\u2019t ready yet. Sign in to it again in a minute.");
490
498
  }
499
+ async function fetchAccountUsername(auth, accountAddress) {
500
+ const usernames = [];
501
+ let cursor = null;
502
+ do {
503
+ const result = await fetchUsernames(auth.lensClient, {
504
+ filter: { linkedTo: evmAddress2(accountAddress) },
505
+ pageSize: PageSize.Fifty,
506
+ cursor
507
+ });
508
+ if (result.isErr()) throw result.error;
509
+ usernames.push(...result.value.items);
510
+ cursor = result.value.pageInfo.next ?? null;
511
+ } while (cursor);
512
+ const preferred = auth.usernameNamespace?.toLowerCase();
513
+ const rank = (username) => username.namespace.toLowerCase() === preferred ? 0 : username.value.startsWith("lens/") ? 1 : 2;
514
+ const [best] = usernames.sort((a, b) => rank(a) - rank(b));
515
+ return best?.localName ?? null;
516
+ }
491
517
  async function signInToCreatedAccount(auth, session, accountAddress) {
492
518
  const switched = await session.switchAccount({ account: evmAddress2(accountAddress) });
493
519
  if (switched.isErr()) throw switched.error;
@@ -521,6 +547,7 @@ export {
521
547
  checkUsername,
522
548
  uploadAccountMetadata,
523
549
  createLensAccount,
550
+ fetchAccountUsername,
524
551
  signInToCreatedAccount
525
552
  };
526
- //# sourceMappingURL=chunk-2UCSL2CL.js.map
553
+ //# sourceMappingURL=chunk-PJC2S3IU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/constants.ts","../src/core/jwt.ts","../src/core/storage.ts","../src/core/tokens.ts","../src/core/wallet.ts","../src/core/auth.ts","../src/core/onboarding.ts"],"sourcesContent":["// Dependency-free values shared by every entry point, including the server and Convex ones.\n\nexport type LensEnvironmentName = \"mainnet\" | \"testnet\"\n\nconst LENS_API_ORIGINS: Record<LensEnvironmentName, string> = {\n mainnet: \"https://api.lens.xyz\",\n testnet: \"https://api.testnet.lens.xyz\",\n}\n\n// Lens signs its tokens as the API origin, and publishes its keys under it.\nexport function lensApiOrigin(environment: LensEnvironmentName = \"mainnet\"): string {\n return LENS_API_ORIGINS[environment]\n}\n\nexport const LENS_CHAIN_IDS: Record<LensEnvironmentName, number> = {\n mainnet: 232,\n testnet: 37111,\n}\n\n// Lens access and ID tokens are valid for 10 minutes.\nexport const LENS_TOKEN_LIFETIME_MS = 10 * 60 * 1000\n\nexport const ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/\n\n// The token the server issues for Convex (server/, convex/, cli/). Both sides must agree on these.\nexport const DEFAULT_CONVEX_TOKEN_ISSUER = \"https://lens-convex-auth.local\"\nexport const DEFAULT_CONVEX_TOKEN_AUDIENCE = \"convex\"\nexport const DEFAULT_CONVEX_TOKEN_KEY_ID = \"convex-auth-1\"\nexport const DEFAULT_CONVEX_TOKEN_ENDPOINT = \"/api/convex-token\"\n","// Claims of a JWT, without verifying it (the server verifies). Null if it isn't a JWT.\nexport function decodeJwtPayload(token: string): Record<string, unknown> | null {\n try {\n const payload = token.split(\".\")[1]\n if (!payload) return null\n const base64 = payload.replace(/-/g, \"+\").replace(/_/g, \"/\")\n const binary = atob(base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), \"=\"))\n const json = new TextDecoder().decode(Uint8Array.from(binary, (c) => c.charCodeAt(0)))\n const claims = JSON.parse(json)\n return claims && typeof claims === \"object\" ? claims : null\n } catch {\n return null\n }\n}\n\n// When a JWT expires (ms since epoch), from its `exp` claim\nexport function jwtExpiresAt(token: string): number | null {\n const exp = Number(decodeJwtPayload(token)?.exp)\n return Number.isFinite(exp) && exp > 0 ? exp * 1000 : null\n}\n\n// The Lens account a Lens ID token acts for (`act.sub`), lowercased, and the session it belongs to.\n// Null for tokens without an account (onboarding users) or that aren't JWTs.\nexport function lensSessionFromIdToken(idToken: string): { account: string; sessionId: string } | null {\n const claims = decodeJwtPayload(idToken)\n const act = claims?.act as { sub?: unknown } | null | undefined\n if (typeof act?.sub !== \"string\") return null\n return { account: act.sub.toLowerCase(), sessionId: String(claims?.sid ?? \"\") }\n}\n","import type { IStorageProvider } from \"@lens-protocol/client\"\nimport type { TokenService } from \"./tokens\"\n\n// Storage for the Lens SDK that keeps its credentials in the TokenService, so the SDK and the app\n// share one copy of the session. Everything else the SDK stores goes to localStorage under a prefix.\nexport class LensTokenStorage implements IStorageProvider {\n constructor(private tokens: TokenService, private prefix: string) {}\n\n private isCredentials(key: string) {\n return key.includes(\"credentials\") || key.includes(\"session\")\n }\n\n // The SDK only accepts a stored credentials item whose metadata is exactly\n // { version, createdAt, updatedAt }, so keep the metadata it wrote and hand it back unchanged.\n private metadataKey(key: string) {\n return `${this.prefix}${key}:metadata`\n }\n\n private credentialsMetadata(key: string) {\n const stored = localStorage.getItem(this.metadataKey(key))\n if (stored) return JSON.parse(stored)\n // Tokens stored before the metadata was kept: 3 is the SDK's current credentials schema version.\n const now = Date.now()\n return { version: 3, createdAt: now, updatedAt: now }\n }\n\n getItem(key: string): string | null {\n if (typeof window === \"undefined\") return null\n try {\n if (!this.isCredentials(key)) return localStorage.getItem(this.prefix + key)\n const tokens = this.tokens.getStoredTokens()\n if (!tokens) return null\n return JSON.stringify({\n data: { accessToken: tokens.accessToken, idToken: tokens.idToken, refreshToken: tokens.refreshToken },\n metadata: this.credentialsMetadata(key),\n })\n } catch {\n return null\n }\n }\n\n setItem(key: string, value: string): void {\n if (typeof window === \"undefined\") return\n try {\n if (!this.isCredentials(key)) return localStorage.setItem(this.prefix + key, value)\n const parsed = JSON.parse(value)\n const data = typeof parsed.data === \"string\" ? JSON.parse(parsed.data) : parsed.data\n if (data?.accessToken && data?.idToken && data?.refreshToken) {\n this.tokens.storeCredentials(data)\n localStorage.setItem(this.metadataKey(key), JSON.stringify(parsed.metadata))\n }\n } catch {}\n }\n\n removeItem(key: string): void {\n if (typeof window === \"undefined\") return\n try {\n if (!this.isCredentials(key)) return localStorage.removeItem(this.prefix + key)\n this.tokens.clearTokens()\n localStorage.removeItem(this.metadataKey(key))\n } catch {}\n }\n}\n","import { LENS_TOKEN_LIFETIME_MS } from \"./constants\"\nimport { jwtExpiresAt } from \"./jwt\"\n\nexport interface TokenData {\n accessToken: string\n idToken: string\n refreshToken: string\n expiresAt: number // when the access token expires (ms since epoch)\n}\n\nexport type LensCredentials = Pick<TokenData, \"accessToken\" | \"idToken\" | \"refreshToken\">\n\n// Dispatched on window whenever tokens are stored or cleared in this tab\nexport const TOKENS_CHANGED_EVENT = \"lens-convex-auth:tokens-changed\"\n\n// Refresh a minute before expiry for smoother UX\nconst REFRESH_BUFFER_MS = 60 * 1000\n\nconst REFRESH_MUTATION = `\n mutation Refresh($request: RefreshRequest!) {\n refresh(request: $request) {\n ... on AuthenticationTokens {\n accessToken\n idToken\n refreshToken\n }\n ... on ForbiddenError {\n reason\n }\n }\n }\n`\n\nfunction notifyTokensChanged() {\n try {\n window.dispatchEvent(new Event(TOKENS_CHANGED_EVENT))\n } catch {}\n}\n\n// Keeps the Lens session's tokens in localStorage, the single place every part of the app (the Lens\n// SDK, Convex, API calls) reads them from, and refreshes them.\nexport class TokenService {\n readonly storageKeys: { accessToken: string; idToken: string; refreshToken: string; expiresAt: string }\n private refreshPromise: Promise<TokenData | null> | null = null\n\n constructor(private options: { storagePrefix: string; graphqlUrl: string }) {\n const p = options.storagePrefix\n this.storageKeys = {\n accessToken: `${p}access_token`,\n idToken: `${p}id_token`,\n refreshToken: `${p}refresh_token`,\n expiresAt: `${p}token_expires_at`,\n }\n }\n\n storeTokens(tokens: TokenData): void {\n if (typeof window === \"undefined\") return\n try {\n localStorage.setItem(this.storageKeys.accessToken, tokens.accessToken)\n localStorage.setItem(this.storageKeys.idToken, tokens.idToken)\n localStorage.setItem(this.storageKeys.refreshToken, tokens.refreshToken)\n localStorage.setItem(this.storageKeys.expiresAt, tokens.expiresAt.toString())\n } catch {}\n notifyTokensChanged()\n }\n\n storeCredentials(credentials: LensCredentials): void {\n this.storeTokens({ ...credentials, expiresAt: Date.now() + LENS_TOKEN_LIFETIME_MS })\n }\n\n getStoredTokens(): TokenData | null {\n if (typeof window === \"undefined\") return null\n try {\n const accessToken = localStorage.getItem(this.storageKeys.accessToken)\n const idToken = localStorage.getItem(this.storageKeys.idToken)\n const refreshToken = localStorage.getItem(this.storageKeys.refreshToken)\n const storedExpiresAt = localStorage.getItem(this.storageKeys.expiresAt)\n if (!accessToken || !idToken || !refreshToken) return null\n // The access token's own expiry. The stored value is only an estimate (store time + 10 min),\n // which marks tokens read back from an old session as fresh long after they expired.\n const expiresAt = jwtExpiresAt(accessToken) ?? (storedExpiresAt ? parseInt(storedExpiresAt, 10) : 0)\n return { accessToken, idToken, refreshToken, expiresAt }\n } catch {\n return null\n }\n }\n\n clearTokens(): void {\n if (typeof window === \"undefined\") return\n try {\n for (const key of Object.values(this.storageKeys)) localStorage.removeItem(key)\n } catch {}\n notifyTokensChanged()\n }\n\n // Current access token, refreshed first if it's about to expire\n async getValidAccessToken(): Promise<string | null> {\n const tokens = this.getStoredTokens()\n if (!tokens) return null\n if (tokens.expiresAt > Date.now() + REFRESH_BUFFER_MS) return tokens.accessToken\n return (await this.refreshTokens())?.accessToken ?? null\n }\n\n // ID token for authenticating to your backend (Convex, API routes), refreshed when it's about to\n // expire (by the token's own `exp` claim). `forceRefresh` is for when the backend rejected it.\n async getFreshIdToken(forceRefresh = false): Promise<string | null> {\n const tokens = this.getStoredTokens()\n if (!tokens) return null\n const expiresAt = jwtExpiresAt(tokens.idToken) ?? 0\n const fresh = expiresAt > Date.now() + REFRESH_BUFFER_MS\n // A forced refresh right after another tab or the background refresher got new tokens reuses them\n const justIssued = expiresAt > Date.now() + 2 * REFRESH_BUFFER_MS\n if (fresh && (!forceRefresh || justIssued)) return tokens.idToken\n return (await this.refreshTokens())?.idToken ?? null\n }\n\n async isAuthenticated(): Promise<boolean> {\n return !!(await this.getValidAccessToken())\n }\n\n // Concurrent calls share one request. Clears the tokens when the session can't be refreshed.\n refreshTokens(): Promise<TokenData | null> {\n this.refreshPromise ??= this.performRefresh().finally(() => {\n this.refreshPromise = null\n })\n return this.refreshPromise\n }\n\n private async performRefresh(): Promise<TokenData | null> {\n const refreshToken = this.getStoredTokens()?.refreshToken\n if (!refreshToken) {\n this.clearTokens()\n return null\n }\n try {\n // Resuming the Lens session only reads these same tokens back, so ask the API for new ones.\n // (Each Lens SDK session keeps its own copy of the tokens and refreshes that copy itself.)\n const response = await fetch(this.options.graphqlUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ query: REFRESH_MUTATION, variables: { request: { refreshToken } } }),\n })\n const data = await response.json()\n const result = data?.data?.refresh\n if (data.errors || !result || result.reason) throw new Error(result?.reason ?? \"Refresh failed\")\n const tokens: TokenData = {\n accessToken: result.accessToken,\n idToken: result.idToken,\n refreshToken: result.refreshToken,\n expiresAt: Date.now() + LENS_TOKEN_LIFETIME_MS,\n }\n this.storeTokens(tokens)\n return tokens\n } catch {\n this.clearTokens()\n return null\n }\n }\n}\n","import { createWalletClient, custom, defineChain as defineViemChain, getAddress, hexToBigInt, hexToNumber, type Account as ViemAccount, type Chain as ViemChain, type Hex, type Transport, type WalletClient } from \"viem\"\nimport { lens as viemLens, lensTestnet as viemLensTestnet } from \"viem/chains\"\nimport { chainConfig } from \"viem/zksync\"\nimport { defineChain, type Chain } from \"thirdweb/chains\"\nimport { EIP1193, type Wallet } from \"thirdweb/wallets\"\nimport type { ThirdwebClient } from \"thirdweb\"\nimport { LENS_CHAIN_IDS, type LensEnvironmentName } from \"./constants\"\n\n// Lens Chain for thirdweb. Without an RPC URL thirdweb uses its own RPC for the chain.\nexport function lensThirdwebChain(environment: LensEnvironmentName, rpcUrl?: string): Chain {\n const testnet = environment === \"testnet\"\n return defineChain({\n id: LENS_CHAIN_IDS[environment],\n name: testnet ? \"Lens Chain Testnet\" : \"Lens Chain\",\n nativeCurrency: testnet\n ? { name: \"GRASS\", symbol: \"GRASS\", decimals: 18 }\n : { name: \"GHO\", symbol: \"GHO\", decimals: 18 },\n ...(rpcUrl ? { rpc: rpcUrl } : {}),\n ...(testnet ? { testnet: true as const } : {}),\n })\n}\n\n// Lens Chain with the zkSync config (same as `chains.mainnet` from @lens-chain/sdk/viem), so viem can\n// sign the sponsored EIP-712 transactions the Lens API returns. Typed as a plain `Chain` because\n// `handleOperationWith` takes a plain viem `WalletClient`.\nexport function lensViemChain(environment: LensEnvironmentName): ViemChain {\n return defineViemChain({ ...(environment === \"testnet\" ? viemLensTestnet : viemLens), ...chainConfig })\n}\n\n// A viem wallet client for the connected thirdweb wallet, as `handleOperationWith` expects:\n// hoisted account and a Lens chain. Works for every thirdweb wallet, not only injected ones.\nexport function createLensWalletClient(opts: {\n wallet: Wallet\n client: ThirdwebClient\n chain: Chain\n viemChain: ViemChain\n}): WalletClient<Transport, ViemChain, ViemAccount> {\n const account = opts.wallet.getAccount()\n if (!account) throw new Error(\"Connect your wallet\")\n const provider = EIP1193.toProvider({ wallet: opts.wallet, chain: opts.chain, client: opts.client })\n return createWalletClient({\n account: getAddress(account.address),\n chain: opts.viemChain,\n transport: custom({\n request: ({ method, params }) => {\n if (method === \"eth_sendTransaction\") {\n // viem sends hex-encoded fields (e.g. `type: \"0x2\"`) that thirdweb's local signers reject.\n // thirdweb re-estimates gas and fees for Lens Chain anyway, so pass only what it needs.\n const [tx] = params as [{ to: Hex; data?: Hex; value?: Hex; nonce?: Hex }]\n return provider.request({\n method,\n params: [{\n to: tx.to,\n data: tx.data,\n value: tx.value ? hexToBigInt(tx.value) : undefined,\n nonce: tx.nonce ? hexToNumber(tx.nonce) : undefined,\n }],\n })\n }\n return provider.request({ method, params })\n },\n }),\n })\n}\n","import { PublicClient, evmAddress, mainnet, signatureFrom, testnet, type SessionClient, type UUID } from \"@lens-protocol/client\"\nimport { createThirdwebClient, type ThirdwebClient } from \"thirdweb\"\nimport type { Chain } from \"thirdweb/chains\"\nimport type { Chain as ViemChain } from \"viem\"\nimport { ADDRESS_RE, DEFAULT_CONVEX_TOKEN_ENDPOINT, lensApiOrigin, type LensEnvironmentName } from \"./constants\"\nimport { lensSessionFromIdToken } from \"./jwt\"\nimport { LensTokenStorage } from \"./storage\"\nimport { TokenService, type LensCredentials } from \"./tokens\"\nimport { lensThirdwebChain, lensViemChain } from \"./wallet\"\n\nexport type LensAuthOptions = {\n /** thirdweb client ID (https://thirdweb.com/dashboard) */\n thirdwebClientId: string\n /** Your Lens app address (https://developer.lens.xyz/apps). Tokens are issued for this app. */\n lensAppAddress: string\n /** Defaults to \"mainnet\" */\n environment?: LensEnvironmentName\n /** Lens Chain RPC for thirdweb. Defaults to thirdweb's RPC. */\n lensChainRpcUrl?: string\n /** Prefix of the localStorage keys the session is stored under. Defaults to \"lens_\". */\n storagePrefix?: string\n /** Route that exchanges a Lens ID token for a Convex token. Defaults to \"/api/convex-token\". */\n convexTokenEndpoint?: string\n /**\n * Username namespace (0x…) new accounts get their username in, and whose usernames are shown first.\n * Defaults to the global Lens namespace.\n */\n usernameNamespace?: string\n}\n\nexport type LensLoginRole = \"ACCOUNT_OWNER\" | \"ACCOUNT_MANAGER\"\n\nexport type LensChallenge = { id: UUID; text: string }\n\nexport type MessageSigner = {\n signMessage: (args: { message: string }) => Promise<string>\n}\n\n// The signed-in Lens account (lowercased address) and its session, read from the stored ID token\nexport type LensSessionInfo = { account: string; sessionId: string }\n\nexport type LensAuth = ReturnType<typeof createLensAuth>\n\n// Challenges are fetched ahead of time so a tap can sign right away: how often they're replaced, and how\n// old one can be to still be used.\nexport const CHALLENGE_REFRESH_MS = 2 * 60 * 1000\nexport const CHALLENGE_MAX_AGE_MS = 4 * 60 * 1000\n\n// On phones and tablets thirdweb opens the wallet app with a deep link to sign (same check as its\n// internal isMobile), and that deep link only works right after a tap.\nexport function opensWalletWithDeepLink() {\n if (typeof navigator === \"undefined\") return false\n const ua = navigator.userAgent\n return /iPhone|iPad|iPod|Android/i.test(ua) || (/Macintosh/.test(ua) && navigator.maxTouchPoints > 1)\n}\n\n// Asks the wallet to sign synchronously (no awaits before it), so call it directly from a click handler.\nexport function signLensChallenge(challenge: LensChallenge, signer: MessageSigner): Promise<string> {\n return signer.signMessage({ message: challenge.text })\n}\n\n// A Lens SDK session's tokens\nexport function sessionCredentials(session: SessionClient): LensCredentials {\n const credentials = session.getCredentials()\n if (credentials.isErr()) throw credentials.error\n if (!credentials.value) throw new Error(\"The Lens session has no credentials\")\n return credentials.value\n}\n\n// Create once per app (at module level) and pass to <LensAuthProvider>.\nexport function createLensAuth(options: LensAuthOptions) {\n if (!options.thirdwebClientId) throw new Error(\"lens-convex-auth: thirdwebClientId is required\")\n if (!ADDRESS_RE.test(options.lensAppAddress ?? \"\")) {\n throw new Error(\"lens-convex-auth: lensAppAddress must be your Lens app address (0x…)\")\n }\n if (options.usernameNamespace !== undefined && !ADDRESS_RE.test(options.usernameNamespace)) {\n throw new Error(\"lens-convex-auth: usernameNamespace must be a Lens namespace address (0x…)\")\n }\n\n const environment: LensEnvironmentName = options.environment ?? \"mainnet\"\n const storagePrefix = options.storagePrefix ?? \"lens_\"\n const appAddress = options.lensAppAddress\n const convexTokenEndpoint = options.convexTokenEndpoint ?? DEFAULT_CONVEX_TOKEN_ENDPOINT\n const usernameNamespace = options.usernameNamespace\n\n const tokens = new TokenService({ storagePrefix, graphqlUrl: `${lensApiOrigin(environment)}/graphql` })\n const thirdwebClient: ThirdwebClient = createThirdwebClient({ clientId: options.thirdwebClientId })\n const chain: Chain = lensThirdwebChain(environment, options.lensChainRpcUrl)\n const viemChain: ViemChain = lensViemChain(environment)\n const lensEnvironment = environment === \"testnet\" ? testnet : mainnet\n const lensClient = PublicClient.create({\n environment: lensEnvironment,\n storage: typeof window !== \"undefined\" ? new LensTokenStorage(tokens, `${storagePrefix}custom_`) : undefined,\n })\n\n // The signed-in account, or null when signed out\n function getSession(): LensSessionInfo | null {\n const idToken = tokens.getStoredTokens()?.idToken\n return idToken ? lensSessionFromIdToken(idToken) : null\n }\n\n // True when there's a valid session, refreshing its tokens first if needed (a session that can't be\n // refreshed is cleared). Also resumes it in the Lens client, so Lens SDK calls and hooks act as the\n // signed-in account.\n async function resumeSession(): Promise<boolean> {\n if (!(await tokens.isAuthenticated())) return false\n if (!lensClient.currentSession?.isSessionClient()) await lensClient.resumeSession()\n return true\n }\n\n // Logging in is split in two (challenge, then sign + authenticate) instead of using `lensClient.login`,\n // so the signature can be requested straight from a tap. On mobile, WalletConnect opens the wallet app\n // with a deep link when asked to sign, and iOS only allows that right after a user gesture: after the\n // challenge round trip the link is blocked and the wallet never shows the request.\n async function requestChallenge(opts: { role: LensLoginRole; account: string; signer: string }): Promise<LensChallenge> {\n const app = evmAddress(appAddress)\n const account = evmAddress(opts.account)\n const signer = evmAddress(opts.signer)\n const challenge = await lensClient.challenge(\n opts.role === \"ACCOUNT_MANAGER\"\n ? { accountManager: { account, app, manager: signer } }\n : { accountOwner: { account, app, owner: signer } },\n )\n if (challenge.isErr()) throw challenge.error\n return challenge.value\n }\n\n async function authenticate(challenge: LensChallenge, signature: string): Promise<SessionClient> {\n const authenticated = await lensClient.authenticate({ id: challenge.id, signature: signatureFrom(signature) })\n if (authenticated.isErr()) throw authenticated.error\n tokens.storeCredentials(sessionCredentials(authenticated.value))\n return authenticated.value\n }\n\n async function logout(): Promise<void> {\n tokens.clearTokens()\n // PublicClient has no logout; logout exists on SessionClient\n const session = lensClient.currentSession\n if (session && session.isSessionClient()) await session.logout()\n }\n\n // fetch() with the Lens ID token as `Authorization: Bearer`, retried once with a refreshed token on 401.\n // Verify it on the server with `getLensSession` from \"lens-convex-auth/server\".\n async function authFetch(input: RequestInfo | URL, init: RequestInit = {}): Promise<Response> {\n const send = async (forceRefresh: boolean) => {\n const idToken = await tokens.getFreshIdToken(forceRefresh)\n const headers = new Headers(init.headers)\n if (idToken) headers.set(\"Authorization\", `Bearer ${idToken}`)\n return fetch(input, { ...init, headers })\n }\n const response = await send(false)\n return response.status === 401 && getSession() ? send(true) : response\n }\n\n // Convex can't verify Lens ID tokens itself (they have no `kid` header), so the server verifies the\n // Lens ID token and issues a Convex token for the same account (see \"lens-convex-auth/server\").\n async function fetchConvexToken(forceRefresh = false): Promise<string | null> {\n const idToken = await tokens.getFreshIdToken(forceRefresh)\n if (!idToken) return null\n try {\n const res = await fetch(convexTokenEndpoint, { method: \"POST\", headers: { Authorization: `Bearer ${idToken}` } })\n if (!res.ok) return null\n const { token } = await res.json()\n return typeof token === \"string\" ? token : null\n } catch {\n return null\n }\n }\n\n return {\n environment,\n appAddress,\n usernameNamespace,\n storagePrefix,\n thirdwebClient,\n chain,\n viemChain,\n lensClient,\n lensEnvironment,\n tokens,\n getSession,\n resumeSession,\n requestChallenge,\n signChallenge: signLensChallenge,\n authenticate,\n logout,\n fetch: authFetch,\n fetchConvexToken,\n }\n}\n","import { PageSize, PublicClient, evmAddress, signatureFrom, uri, type Account, type Cursor, type SessionClient } from \"@lens-protocol/client\"\nimport { canCreateUsername, createAccountWithUsername, fetchAccount, fetchUsername, fetchUsernames } from \"@lens-protocol/client/actions\"\nimport { handleOperationWith } from \"@lens-protocol/client/viem\"\nimport { account as accountMetadata } from \"@lens-protocol/metadata\"\nimport { StorageClient, immutable } from \"@lens-chain/storage-client\"\nimport { getTransactionReceipt } from \"viem/actions\"\nimport type { Wallet } from \"thirdweb/wallets\"\nimport type { LensAuth, LensChallenge } from \"./auth\"\nimport { sessionCredentials } from \"./auth\"\nimport { LENS_CHAIN_IDS } from \"./constants\"\nimport { createLensWalletClient } from \"./wallet\"\n\n// An error whose message can be shown to the user as is.\nexport class OnboardingError extends Error {\n name = \"OnboardingError\"\n}\n\n// Creating an account takes a session as an onboarding user (a wallet signed in without a Lens Account).\n// It runs on its own client, whose storage is in memory, so that session never reaches the app's token\n// storage: until the account exists and is signed in to, the app must not treat the wallet as signed in.\nexport function createOnboardingClient(auth: LensAuth) {\n return PublicClient.create({ environment: auth.lensEnvironment })\n}\n\nexport async function requestOnboardingChallenge(auth: LensAuth, client: PublicClient, walletAddress: string): Promise<LensChallenge> {\n const challenge = await client.challenge({\n onboardingUser: { app: evmAddress(auth.appAddress), wallet: evmAddress(walletAddress) },\n })\n if (challenge.isErr()) throw challenge.error\n return challenge.value\n}\n\nexport async function authenticateOnboarding(client: PublicClient, challenge: LensChallenge, signature: string): Promise<SessionClient> {\n const authenticated = await client.authenticate({ id: challenge.id, signature: signatureFrom(signature) })\n if (authenticated.isErr()) throw authenticated.error\n return authenticated.value\n}\n\n// The global Lens namespace takes lowercase letters, numbers, \"-\" and \"_\", and can't start with \"-\" or \"_\".\n// Its other rules (length, reserved names, price) are checked by the Lens API in checkUsername.\nconst USERNAME_PATTERN = /^[a-z0-9][a-z0-9_-]*$/\n\nexport function usernameFormatError(localName: string): string | null {\n if (!localName) return \"Choose a username\"\n if (/^[-_]/.test(localName)) return \"Start with a letter or a number\"\n if (!USERNAME_PATTERN.test(localName)) return \"Use only lowercase letters, numbers, - and _\"\n return null\n}\n\n// The username to create, in the app's namespace when it has one (else the global Lens namespace)\nfunction usernameInput(auth: LensAuth, localName: string) {\n return auth.usernameNamespace ? { localName, namespace: evmAddress(auth.usernameNamespace) } : { localName }\n}\n\n// Needs no session, so it can run while the user types.\nexport async function isUsernameTaken(auth: LensAuth, localName: string): Promise<boolean> {\n const result = await fetchUsername(auth.lensClient, { username: usernameInput(auth, localName) })\n if (result.isErr()) throw result.error\n return result.value !== null\n}\n\ntype NamespaceValidationFailed = {\n reason: string\n unsatisfiedRules: { required: { message: string }[] } | null\n}\n\nfunction validationFailedMessage(failed: NamespaceValidationFailed) {\n return failed.unsatisfiedRules?.required[0]?.message || failed.reason\n}\n\n// Returns why the username can't be created, or null if it can.\nexport async function checkUsername(auth: LensAuth, session: SessionClient, localName: string): Promise<string | null> {\n const result = await canCreateUsername(session, usernameInput(auth, localName))\n if (result.isErr()) throw result.error\n switch (result.value.__typename) {\n case \"NamespaceOperationValidationPassed\":\n return null\n case \"UsernameTaken\":\n return \"This username is taken\"\n case \"NamespaceOperationValidationFailed\":\n return validationFailedMessage(result.value)\n case \"NamespaceOperationValidationUnknown\":\n return \"This username can’t be created here. Try another one.\"\n }\n}\n\nlet storageClient: StorageClient | null = null\n\nexport type AccountProfile = {\n name?: string\n bio?: string\n picture?: File | null\n}\n\n// Uploads the account metadata (and its picture) to Grove, and returns the metadata URI.\nexport async function uploadAccountMetadata(auth: LensAuth, profile: AccountProfile): Promise<string> {\n storageClient ??= StorageClient.create()\n const acl = immutable(LENS_CHAIN_IDS[auth.environment])\n const picture = profile.picture ? (await storageClient.uploadFile(profile.picture, { acl })).uri : undefined\n const metadata = accountMetadata({\n name: profile.name || undefined,\n bio: profile.bio || undefined,\n picture,\n })\n const { uri: metadataUri } = await storageClient.uploadAsJson(metadata, { acl })\n return metadataUri\n}\n\n// How long to wait for a new account to be listed once its transaction is indexed\nconst ACCOUNT_POLL_ATTEMPTS = 15\nconst ACCOUNT_POLL_INTERVAL_MS = 2000\n\n// Creates an account owned by the onboarding user's wallet. Most apps sponsor it; otherwise the wallet\n// is asked to send the transaction.\nexport async function createLensAccount(\n auth: LensAuth,\n session: SessionClient,\n wallet: Wallet,\n request: { localName: string; metadataUri: string },\n): Promise<Account> {\n const created = await createAccountWithUsername(session, {\n username: usernameInput(auth, request.localName),\n metadataUri: uri(request.metadataUri),\n })\n if (created.isErr()) throw created.error\n const result = created.value\n switch (result.__typename) {\n case \"UsernameTaken\":\n throw new OnboardingError(\"This username is taken\")\n case \"NamespaceOperationValidationFailed\":\n throw new OnboardingError(validationFailedMessage(result))\n case \"TransactionWillFail\":\n throw new OnboardingError(result.reason)\n }\n\n const walletClient = createLensWalletClient({ wallet, client: auth.thirdwebClient, chain: auth.chain, viemChain: auth.viemChain })\n const sent = await handleOperationWith(walletClient)(result)\n if (sent.isErr()) throw sent.error\n const hash = sent.value\n\n const indexed = await session.waitForTransaction(hash)\n if (indexed.isErr()) {\n // The Lens API stops waiting for indexing after 10s on mainnet, so the receipt decides whether\n // the transaction failed. If it can't be read either, the account lookup below still settles it.\n const receipt = await getTransactionReceipt(walletClient, { hash }).catch(() => null)\n if (receipt?.status === \"reverted\") throw indexed.error\n }\n\n for (let attempt = 0; attempt < ACCOUNT_POLL_ATTEMPTS; attempt++) {\n const fetched = await fetchAccount(session, { txHash: hash })\n if (fetched.isOk() && fetched.value) return fetched.value\n await new Promise((resolve) => setTimeout(resolve, ACCOUNT_POLL_INTERVAL_MS))\n }\n throw new OnboardingError(\"Your account was created but isn’t ready yet. Sign in to it again in a minute.\")\n}\n\n// An account's username in the namespace it prefers: the app's namespace, then the global Lens one, then\n// any other. So accounts from apps with their own namespace can sign in too. Null if it has none.\nexport async function fetchAccountUsername(auth: LensAuth, accountAddress: string): Promise<string | null> {\n const usernames: { localName: string; namespace: string; value: string }[] = []\n let cursor: Cursor | null = null\n do {\n const result = await fetchUsernames(auth.lensClient, {\n filter: { linkedTo: evmAddress(accountAddress) },\n pageSize: PageSize.Fifty,\n cursor,\n })\n if (result.isErr()) throw result.error\n usernames.push(...result.value.items)\n cursor = (result.value.pageInfo.next as Cursor | null) ?? null\n } while (cursor)\n const preferred = auth.usernameNamespace?.toLowerCase()\n const rank = (username: { namespace: string; value: string }) =>\n username.namespace.toLowerCase() === preferred ? 0 : username.value.startsWith(\"lens/\") ? 1 : 2\n const [best] = usernames.sort((a, b) => rank(a) - rank(b))\n return best?.localName ?? null\n}\n\n// Signs the app in to the new account without another signature: the onboarding session switches to it,\n// and its tokens are handed to the app's Lens client, like a sign-in from the account list.\nexport async function signInToCreatedAccount(auth: LensAuth, session: SessionClient, accountAddress: string): Promise<void> {\n const switched = await session.switchAccount({ account: evmAddress(accountAddress) })\n if (switched.isErr()) throw switched.error\n auth.tokens.storeCredentials(sessionCredentials(switched.value))\n const resumed = await auth.lensClient.resumeSession()\n if (resumed.isErr()) throw resumed.error\n}\n"],"mappings":"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","names":["testnet","PublicClient","evmAddress","signatureFrom","PublicClient","evmAddress","signatureFrom"]}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { L as LensChallenge, a as LensAuth, T as TokenService, b as LensEnvironmentName } from './auth-Baitf7Ze.js';
2
- export { C as CHALLENGE_MAX_AGE_MS, c as CHALLENGE_REFRESH_MS, d as LENS_CHAIN_IDS, e as LensAuthOptions, f as LensCredentials, g as LensLoginRole, h as LensSessionInfo, M as MessageSigner, i as TOKENS_CHANGED_EVENT, j as TokenData, k as createLensAuth, l as lensApiOrigin, o as opensWalletWithDeepLink, s as signLensChallenge } from './auth-Baitf7Ze.js';
1
+ import { L as LensChallenge, a as LensAuth, T as TokenService, b as LensEnvironmentName } from './auth-vTn7nb6F.js';
2
+ export { C as CHALLENGE_MAX_AGE_MS, c as CHALLENGE_REFRESH_MS, d as LENS_CHAIN_IDS, e as LensAuthOptions, f as LensCredentials, g as LensLoginRole, h as LensSessionInfo, M as MessageSigner, i as TOKENS_CHANGED_EVENT, j as TokenData, k as createLensAuth, l as lensApiOrigin, o as opensWalletWithDeepLink, s as signLensChallenge } from './auth-vTn7nb6F.js';
3
3
  import * as _lens_protocol_client from '@lens-protocol/client';
4
4
  import { PublicClient, SessionClient, Account, IStorageProvider } from '@lens-protocol/client';
5
5
  import { Wallet } from 'thirdweb/wallets';
@@ -15,7 +15,7 @@ declare function requestOnboardingChallenge(auth: LensAuth, client: PublicClient
15
15
  declare function authenticateOnboarding(client: PublicClient, challenge: LensChallenge, signature: string): Promise<SessionClient>;
16
16
  declare function usernameFormatError(localName: string): string | null;
17
17
  declare function isUsernameTaken(auth: LensAuth, localName: string): Promise<boolean>;
18
- declare function checkUsername(session: SessionClient, localName: string): Promise<string | null>;
18
+ declare function checkUsername(auth: LensAuth, session: SessionClient, localName: string): Promise<string | null>;
19
19
  type AccountProfile = {
20
20
  name?: string;
21
21
  bio?: string;
@@ -26,6 +26,7 @@ declare function createLensAccount(auth: LensAuth, session: SessionClient, walle
26
26
  localName: string;
27
27
  metadataUri: string;
28
28
  }): Promise<Account>;
29
+ declare function fetchAccountUsername(auth: LensAuth, accountAddress: string): Promise<string | null>;
29
30
  declare function signInToCreatedAccount(auth: LensAuth, session: SessionClient, accountAddress: string): Promise<void>;
30
31
 
31
32
  declare class LensTokenStorage implements IStorageProvider {
@@ -55,4 +56,4 @@ declare function createLensWalletClient(opts: {
55
56
  viemChain: Chain$1;
56
57
  }): WalletClient<Transport, Chain$1, Account$1>;
57
58
 
58
- export { type AccountProfile, LensAuth, LensChallenge, LensEnvironmentName, LensTokenStorage, OnboardingError, TokenService, authenticateOnboarding, checkUsername, createLensAccount, createLensWalletClient, createOnboardingClient, decodeJwtPayload, isUsernameTaken, lensSessionFromIdToken, lensThirdwebChain, lensViemChain, requestOnboardingChallenge, signInToCreatedAccount, uploadAccountMetadata, usernameFormatError };
59
+ export { type AccountProfile, LensAuth, LensChallenge, LensEnvironmentName, LensTokenStorage, OnboardingError, TokenService, authenticateOnboarding, checkUsername, createLensAccount, createLensWalletClient, createOnboardingClient, decodeJwtPayload, fetchAccountUsername, isUsernameTaken, lensSessionFromIdToken, lensThirdwebChain, lensViemChain, requestOnboardingChallenge, signInToCreatedAccount, uploadAccountMetadata, usernameFormatError };
package/dist/index.js CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  createLensWalletClient,
15
15
  createOnboardingClient,
16
16
  decodeJwtPayload,
17
+ fetchAccountUsername,
17
18
  isUsernameTaken,
18
19
  lensApiOrigin,
19
20
  lensSessionFromIdToken,
@@ -25,7 +26,7 @@ import {
25
26
  signLensChallenge,
26
27
  uploadAccountMetadata,
27
28
  usernameFormatError
28
- } from "./chunk-2UCSL2CL.js";
29
+ } from "./chunk-PJC2S3IU.js";
29
30
  export {
30
31
  CHALLENGE_MAX_AGE_MS,
31
32
  CHALLENGE_REFRESH_MS,
@@ -41,6 +42,7 @@ export {
41
42
  createLensWalletClient,
42
43
  createOnboardingClient,
43
44
  decodeJwtPayload,
45
+ fetchAccountUsername,
44
46
  isUsernameTaken,
45
47
  lensApiOrigin,
46
48
  lensSessionFromIdToken,
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { Account } from 'thirdweb/wallets';
3
3
  import { ConvexReactClient } from 'convex/react';
4
- import { a as LensAuth } from '../auth-Baitf7Ze.js';
4
+ import { a as LensAuth } from '../auth-vTn7nb6F.js';
5
5
  import { ConnectButtonProps } from 'thirdweb/react';
6
6
  import '@lens-protocol/client';
7
7
  import 'thirdweb/chains';
@@ -8,6 +8,7 @@ import {
8
8
  checkUsername,
9
9
  createLensAccount,
10
10
  createOnboardingClient,
11
+ fetchAccountUsername,
11
12
  isUsernameTaken,
12
13
  opensWalletWithDeepLink,
13
14
  requestOnboardingChallenge,
@@ -15,7 +16,7 @@ import {
15
16
  signLensChallenge,
16
17
  uploadAccountMetadata,
17
18
  usernameFormatError
18
- } from "../chunk-2UCSL2CL.js";
19
+ } from "../chunk-PJC2S3IU.js";
19
20
 
20
21
  // src/react/provider.tsx
21
22
  import * as React4 from "react";
@@ -486,7 +487,7 @@ function CreateAccountForm({ ownerAddress, onCreated, onBack }) {
486
487
  const localName = username;
487
488
  if (!created.current) {
488
489
  setStep({ status: "checking" });
489
- const reason = await checkUsername(onboarding, localName);
490
+ const reason = await checkUsername(auth, onboarding, localName);
490
491
  if (reason) {
491
492
  setUsernameError({ localName, message: reason });
492
493
  setStep(null);
@@ -497,7 +498,7 @@ function CreateAccountForm({ ownerAddress, onCreated, onBack }) {
497
498
  setStep({ status: "creating" });
498
499
  if (!wallet) throw new OnboardingError("Connect your wallet");
499
500
  const account = await createLensAccount(auth, onboarding, wallet, { localName, metadataUri });
500
- created.current = { address: account.address, localName: account.username?.localName ?? localName };
501
+ created.current = { address: account.address, localName };
501
502
  }
502
503
  setStep({ status: "signing-in" });
503
504
  await signInToCreatedAccount(auth, onboarding, created.current.address);
@@ -944,14 +945,20 @@ function AccountDialogBody({ wallet, creating, setCreating }) {
944
945
  const { auth } = useLensAuth();
945
946
  const { completeSignIn } = useAccountDialogState();
946
947
  const isDesktop = useMediaQuery("(min-width: 768px)");
947
- const { data, loading } = useAccountsAvailable({ managedBy: evmAddress(wallet.address), includeOwned: true });
948
+ const { data, loading: loadingAccounts } = useAccountsAvailable({ managedBy: evmAddress(wallet.address), includeOwned: true });
948
949
  const accounts = data?.items;
949
- const hasAccounts = !!accounts?.some((item) => item.account.username?.localName);
950
+ const usernames = useAccountUsernames(auth, accounts);
951
+ const loading = loadingAccounts || !!accounts && !usernames;
952
+ const usernameOf = React3.useCallback((acc) => {
953
+ const resolved = usernames?.[acc.address.toLowerCase()];
954
+ return resolved === void 0 ? acc.username?.localName ?? null : resolved;
955
+ }, [usernames]);
956
+ const hasAccounts = !loading && !!accounts?.some((item) => usernameOf(item.account));
950
957
  const showCreate = creating || !loading && !hasAccounts;
951
958
  const signIn = async (account, challenge) => {
952
959
  const signature = await auth.signChallenge(challenge, wallet);
953
960
  await auth.authenticate(challenge, signature);
954
- completeSignIn({ address: account.address.toLowerCase(), username: account.username?.localName ?? null });
961
+ completeSignIn({ address: account.address.toLowerCase(), username: usernameOf(account) });
955
962
  };
956
963
  const handleCreated = async (created) => {
957
964
  completeSignIn({ address: created.address.toLowerCase(), username: created.localName });
@@ -973,9 +980,27 @@ function AccountDialogBody({ wallet, creating, setCreating }) {
973
980
  onCreated: handleCreated,
974
981
  onBack: hasAccounts ? () => setCreating(false) : void 0
975
982
  }
976
- ) : /* @__PURE__ */ jsx11(AccountList, { auth, accounts, loading, ownerAddress: wallet.address, onSign: signIn, onCreate: () => setCreating(true) }) })
983
+ ) : /* @__PURE__ */ jsx11(AccountList, { auth, accounts, usernameOf, loading, ownerAddress: wallet.address, onSign: signIn, onCreate: () => setCreating(true) }) })
977
984
  ] });
978
985
  }
986
+ function useAccountUsernames(auth, accounts) {
987
+ const key = accounts?.map((item) => item.account.address.toLowerCase()).join(",");
988
+ const [usernames, setUsernames] = React3.useState(null);
989
+ React3.useEffect(() => {
990
+ if (key === void 0) return;
991
+ let cancelled = false;
992
+ const addresses = key ? key.split(",") : [];
993
+ Promise.all(addresses.map(
994
+ (address) => fetchAccountUsername(auth, address).then((username) => [[address, username]], () => [])
995
+ )).then((entries) => {
996
+ if (!cancelled) setUsernames({ key, byAddress: Object.fromEntries(entries.flat()) });
997
+ });
998
+ return () => {
999
+ cancelled = true;
1000
+ };
1001
+ }, [auth, key]);
1002
+ return usernames && usernames.key === key ? usernames.byAddress : void 0;
1003
+ }
979
1004
  function fetchChallenge(auth, acc, ownerAddress) {
980
1005
  return auth.requestChallenge({
981
1006
  role: acc.isOwner ? "ACCOUNT_OWNER" : "ACCOUNT_MANAGER",
@@ -983,7 +1008,7 @@ function fetchChallenge(auth, acc, ownerAddress) {
983
1008
  signer: ownerAddress
984
1009
  });
985
1010
  }
986
- function AccountList({ auth, accounts, loading, ownerAddress, onSign, onCreate }) {
1011
+ function AccountList({ auth, accounts, usernameOf, loading, ownerAddress, onSign, onCreate }) {
987
1012
  const [step, setStep] = React3.useState(null);
988
1013
  const [errorId, setErrorId] = React3.useState(null);
989
1014
  const [challenges, setChallenges] = React3.useState({});
@@ -995,11 +1020,19 @@ function AccountList({ auth, accounts, loading, ownerAddress, onSign, onCreate }
995
1020
  fetchChallenge(auth, acc, ownerAddress).then((challenge) => setChallenges((prev) => ({ ...prev, [id]: { owner: ownerAddress, challenge, fetchedAt: Date.now() } }))).catch(() => {
996
1021
  });
997
1022
  }, [auth, ownerAddress]);
1023
+ const sharedUsernames = React3.useMemo(() => {
1024
+ const counts = /* @__PURE__ */ new Map();
1025
+ for (const { acc } of selectable) {
1026
+ const username = usernameOf(acc);
1027
+ if (username) counts.set(username, (counts.get(username) ?? 0) + 1);
1028
+ }
1029
+ return new Set([...counts].filter(([, count]) => count > 1).map(([username]) => username));
1030
+ }, [selectable, usernameOf]);
998
1031
  React3.useEffect(() => {
999
1032
  const refresh = () => {
1000
1033
  if (document.visibilityState !== "visible") return;
1001
1034
  for (const { acc, id } of selectable) {
1002
- if (acc.username?.localName) prefetch(acc, id);
1035
+ if (usernameOf(acc)) prefetch(acc, id);
1003
1036
  }
1004
1037
  };
1005
1038
  refresh();
@@ -1009,7 +1042,7 @@ function AccountList({ auth, accounts, loading, ownerAddress, onSign, onCreate }
1009
1042
  clearInterval(interval);
1010
1043
  document.removeEventListener("visibilitychange", refresh);
1011
1044
  };
1012
- }, [selectable, prefetch]);
1045
+ }, [selectable, usernameOf, prefetch]);
1013
1046
  const readyChallenge = (id) => {
1014
1047
  if (step?.id === id && step.status === "sign") return step.challenge;
1015
1048
  const prefetched = challenges[id];
@@ -1044,7 +1077,7 @@ function AccountList({ auth, accounts, loading, ownerAddress, onSign, onCreate }
1044
1077
  }
1045
1078
  return /* @__PURE__ */ jsxs5("div", { className: "py-4 space-y-3", children: [
1046
1079
  /* @__PURE__ */ jsx11("ul", { className: "space-y-2 max-h-80 overflow-y-auto", children: selectable.map(({ acc, id }) => {
1047
- const username = acc.username?.localName;
1080
+ const username = usernameOf(acc);
1048
1081
  if (!username) return null;
1049
1082
  const isLoading = step?.id === id && step.status === "loading";
1050
1083
  const awaitingSignature = step?.id === id && step.status === "sign";
@@ -1057,7 +1090,15 @@ function AccountList({ auth, accounts, loading, ownerAddress, onSign, onCreate }
1057
1090
  onClick: () => handleClick(acc, id),
1058
1091
  disabled: step?.status === "loading",
1059
1092
  children: [
1060
- /* @__PURE__ */ jsx11("span", { className: "truncate", children: username }),
1093
+ /* @__PURE__ */ jsxs5("span", { className: "truncate", children: [
1094
+ username,
1095
+ sharedUsernames.has(username) && /* @__PURE__ */ jsxs5("span", { className: "text-muted-foreground", children: [
1096
+ " \xB7 ",
1097
+ acc.address.slice(0, 6),
1098
+ "\u2026",
1099
+ acc.address.slice(-4)
1100
+ ] })
1101
+ ] }),
1061
1102
  isLoading && /* @__PURE__ */ jsx11(Loader22, { className: "size-4 animate-spin text-muted-foreground" }),
1062
1103
  awaitingSignature && /* @__PURE__ */ jsx11("span", { className: "text-sm font-medium text-primary", children: "Sign in" })
1063
1104
  ]
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/provider.tsx","../../src/react/AccountDialog.tsx","../../src/react/CreateAccountForm.tsx","../../src/react/utils.ts","../../src/react/ui/button.tsx","../../src/react/ui/input.tsx","../../src/react/ui/textarea.tsx","../../src/react/ui/avatar.tsx","../../src/react/ui/field.tsx","../../src/react/ui/label.tsx","../../src/react/ui/input-group.tsx","../../src/react/dom.ts","../../src/react/ui/dialog.tsx","../../src/react/ui/drawer.tsx","../../src/react/SignInButton.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { LensProvider } from \"@lens-protocol/react\"\nimport { ThirdwebProvider, useActiveAccount, useActiveWallet, useDisconnect } from \"thirdweb/react\"\nimport type { Account as ThirdwebAccount } from \"thirdweb/wallets\"\nimport { ConvexProviderWithAuth, useConvexAuth, type ConvexReactClient } from \"convex/react\"\nimport type { LensAuth } from \"../core/auth\"\nimport { TOKENS_CHANGED_EVENT } from \"../core/tokens\"\nimport { AccountDialog } from \"./AccountDialog\"\n\nexport type SignedInAccount = {\n /** Lens account address, lowercased */\n address: string\n /** Lens username (local name), when known */\n username: string | null\n}\n\nexport type LensAuthStatus =\n /** Reading the stored session (first render, and during SSR) */\n | \"loading\"\n /** No wallet and no Lens session */\n | \"signed-out\"\n /** Wallet connected, no Lens account signed in yet: the account dialog is open */\n | \"choosing-account\"\n /** Signed in to a Lens account (Convex is authenticated as it too) */\n | \"signed-in\"\n\nexport type LensAuthContextValue = {\n auth: LensAuth\n status: LensAuthStatus\n isLoading: boolean\n isSignedIn: boolean\n /** The connected thirdweb wallet account */\n wallet: ThirdwebAccount | undefined\n /** The signed-in Lens account */\n account: SignedInAccount | null\n /** Ends the Lens session and disconnects the wallet */\n signOut: () => Promise<void>\n /** Opens the account dialog, e.g. to switch to another account */\n openAccountDialog: () => void\n}\n\ntype AccountDialogState = {\n open: boolean\n // True while a wallet is connected without a Lens session: the dialog can't be dismissed\n required: boolean\n setOpen: (open: boolean) => void\n completeSignIn: (account: SignedInAccount) => void\n}\n\nconst LensAuthContext = React.createContext<LensAuthContextValue | null>(null)\nconst AccountDialogContext = React.createContext<AccountDialogState | null>(null)\n\nexport function useLensAuth(): LensAuthContextValue {\n const ctx = React.useContext(LensAuthContext)\n if (!ctx) throw new Error(\"useLensAuth must be used within <LensAuthProvider>\")\n return ctx\n}\n\nexport function useAccountDialogState(): AccountDialogState {\n const ctx = React.useContext(AccountDialogContext)\n if (!ctx) throw new Error(\"<AccountDialog> must be used within <LensAuthProvider>\")\n return ctx\n}\n\nfunction subscribeToTokens(onChange: () => void) {\n window.addEventListener(TOKENS_CHANGED_EVENT, onChange)\n // Signing in or out in another tab\n window.addEventListener(\"storage\", onChange)\n return () => {\n window.removeEventListener(TOKENS_CHANGED_EVENT, onChange)\n window.removeEventListener(\"storage\", onChange)\n }\n}\n\n// Identifies the stored Lens session: its id plus the account it acts for. Token refreshes keep it the\n// same; signing in again, or as another account, changes it. Undefined until read on the client.\nfunction useSessionKey(auth: LensAuth): string | null | undefined {\n return React.useSyncExternalStore(\n subscribeToTokens,\n () => {\n const session = auth.getSession()\n return session ? `${session.sessionId}:${session.account}` : null\n },\n () => undefined,\n )\n}\n\n// Signs Convex in as the Lens account the user signed in with. A new session gets a new\n// fetchAccessToken, which makes Convex fetch its token again.\nfunction createUseConvexAuth(auth: LensAuth) {\n return function useLensConvexAuth() {\n const sessionKey = useSessionKey(auth)\n const fetchAccessToken = React.useCallback(\n async ({ forceRefreshToken }: { forceRefreshToken: boolean }) =>\n sessionKey ? auth.fetchConvexToken(forceRefreshToken) : null,\n [sessionKey],\n )\n return { isLoading: sessionKey === undefined, isAuthenticated: !!sessionKey, fetchAccessToken }\n }\n}\n\nexport type LensAuthProviderProps = {\n /** From createLensAuth(), created once at module level */\n auth: LensAuth\n /** Your ConvexReactClient. Omit to use the package without Convex. */\n convex?: ConvexReactClient\n /**\n * Called after the user signs in from the account dialog (picking an account or creating one), once\n * Convex accepts the session. A good place to create the user's row: `convex.mutation(api.users.ensure)`\n */\n onSignIn?: (account: SignedInAccount) => void | Promise<void>\n /** Render the account dialog. Set to false to render <AccountDialog /> yourself. Defaults to true. */\n accountDialog?: boolean\n children: React.ReactNode\n}\n\n// Wraps the app in thirdweb, Lens and (optionally) Convex providers wired to one session.\nexport function LensAuthProvider({ auth, convex, onSignIn, accountDialog = true, children }: LensAuthProviderProps) {\n const [useConvexAuthHook] = React.useState(() => createUseConvexAuth(auth))\n const content = (\n <LensAuthState auth={auth} onSignIn={onSignIn} withConvex={!!convex}>\n {children}\n {accountDialog && <AccountDialog />}\n </LensAuthState>\n )\n return (\n <ThirdwebProvider>\n <LensProvider client={auth.lensClient}>\n {convex ? (\n <ConvexProviderWithAuth client={convex} useAuth={useConvexAuthHook}>\n {content}\n </ConvexProviderWithAuth>\n ) : content}\n </LensProvider>\n </ThirdwebProvider>\n )\n}\n\nfunction readSelectedAccount(auth: LensAuth, address: string): string | null {\n try {\n const stored = JSON.parse(localStorage.getItem(`${auth.storagePrefix}account`) ?? \"null\")\n return stored?.address === address && typeof stored.username === \"string\" ? stored.username : null\n } catch {\n return null\n }\n}\n\nfunction writeSelectedAccount(auth: LensAuth, account: SignedInAccount | null) {\n try {\n const key = `${auth.storagePrefix}account`\n if (account) localStorage.setItem(key, JSON.stringify(account))\n else localStorage.removeItem(key)\n } catch {}\n}\n\nfunction LensAuthState({ auth, onSignIn, withConvex, children }: {\n auth: LensAuth\n onSignIn?: LensAuthProviderProps[\"onSignIn\"]\n withConvex: boolean\n children: React.ReactNode\n}) {\n const wallet = useActiveAccount()\n const activeWallet = useActiveWallet()\n const { disconnect } = useDisconnect()\n const sessionKey = useSessionKey(auth)\n const [manualOpen, setManualOpen] = React.useState(false)\n const [pendingSignIn, setPendingSignIn] = React.useState<SignedInAccount | null>(null)\n\n const account = React.useMemo<SignedInAccount | null>(() => {\n if (!sessionKey) return null\n const address = sessionKey.slice(sessionKey.lastIndexOf(\":\") + 1)\n return { address, username: readSelectedAccount(auth, address) }\n }, [auth, sessionKey])\n\n const status: LensAuthStatus =\n sessionKey === undefined ? \"loading\"\n : sessionKey ? \"signed-in\"\n : wallet ? \"choosing-account\"\n : \"signed-out\"\n\n useBackgroundRefresh(auth)\n\n // A connected wallet checks the stored session is still valid (refreshing it or clearing it)\n React.useEffect(() => {\n if (wallet) void auth.resumeSession().catch(() => {})\n }, [auth, wallet?.address])\n\n const signOut = React.useCallback(async () => {\n setManualOpen(false)\n writeSelectedAccount(auth, null)\n try {\n await auth.logout()\n } finally {\n if (activeWallet) disconnect(activeWallet)\n }\n }, [auth, activeWallet, disconnect])\n\n const value = React.useMemo<LensAuthContextValue>(() => ({\n auth,\n status,\n isLoading: status === \"loading\",\n isSignedIn: status === \"signed-in\",\n wallet,\n account,\n signOut,\n openAccountDialog: () => setManualOpen(true),\n }), [auth, status, wallet, account, signOut])\n\n const required = status === \"choosing-account\"\n const dialog = React.useMemo<AccountDialogState>(() => ({\n open: required || (manualOpen && !!wallet),\n required,\n setOpen: (open) => {\n if (open) setManualOpen(true)\n else if (!required) setManualOpen(false)\n },\n completeSignIn: (signedIn) => {\n writeSelectedAccount(auth, signedIn)\n setManualOpen(false)\n if (onSignIn) setPendingSignIn(signedIn)\n },\n }), [auth, required, manualOpen, wallet, onSignIn])\n\n return (\n <LensAuthContext.Provider value={value}>\n <AccountDialogContext.Provider value={dialog}>\n {children}\n {pendingSignIn && onSignIn && (\n withConvex\n ? <ConvexSignInCallback account={pendingSignIn} onSignIn={onSignIn} done={() => setPendingSignIn(null)} />\n : <SignInCallback account={pendingSignIn} onSignIn={onSignIn} done={() => setPendingSignIn(null)} />\n )}\n </AccountDialogContext.Provider>\n </LensAuthContext.Provider>\n )\n}\n\ntype SignInCallbackProps = {\n account: SignedInAccount\n onSignIn: NonNullable<LensAuthProviderProps[\"onSignIn\"]>\n done: () => void\n}\n\nfunction SignInCallback({ account, onSignIn, done }: SignInCallbackProps) {\n React.useEffect(() => {\n Promise.resolve(onSignIn(account)).catch((err) => console.error(\"lens-convex-auth: onSignIn failed\", err)).finally(done)\n }, [account])\n return null\n}\n\n// Waits until Convex accepts the new session, so onSignIn can call authenticated Convex functions\nfunction ConvexSignInCallback(props: SignInCallbackProps) {\n const { isAuthenticated, isLoading } = useConvexAuth()\n return isAuthenticated && !isLoading ? <SignInCallback {...props} /> : null\n}\n\n// Refreshes the tokens a minute before they expire, so Convex and API calls always have a fresh one\nfunction useBackgroundRefresh(auth: LensAuth) {\n React.useEffect(() => {\n let timeout: ReturnType<typeof setTimeout> | undefined\n let stopped = false\n\n // Runs again whenever tokens are stored or cleared (a sign-in, a refresh, another tab)\n const schedule = () => {\n if (timeout) clearTimeout(timeout)\n timeout = undefined\n const tokens = auth.tokens.getStoredTokens()\n if (stopped || !tokens?.expiresAt) return\n const delay = Math.max(1000, tokens.expiresAt - Date.now() - 60 * 1000)\n timeout = setTimeout(() => void auth.tokens.refreshTokens(), delay)\n }\n\n const unsubscribe = subscribeToTokens(schedule)\n ;(async () => {\n try {\n await auth.resumeSession()\n } catch {}\n schedule()\n })()\n\n return () => {\n stopped = true\n unsubscribe()\n if (timeout) clearTimeout(timeout)\n }\n }, [auth])\n}\n","import * as React from \"react\"\nimport { useAccountsAvailable } from \"@lens-protocol/react\"\nimport { evmAddress, type Account, type AccountAvailable } from \"@lens-protocol/client\"\nimport type { Account as ThirdwebAccount } from \"thirdweb/wallets\"\nimport { Loader2 } from \"lucide-react\"\nimport { CHALLENGE_MAX_AGE_MS, CHALLENGE_REFRESH_MS, opensWalletWithDeepLink, type LensAuth, type LensChallenge } from \"../core/auth\"\nimport { useAccountDialogState, useLensAuth } from \"./provider\"\nimport { CreateAccountForm, type CreatedAccount } from \"./CreateAccountForm\"\nimport { useMediaQuery } from \"./dom\"\nimport { Button } from \"./ui/button\"\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from \"./ui/dialog\"\nimport { Drawer, DrawerContent, DrawerDescription, DrawerHeader, DrawerTitle } from \"./ui/drawer\"\n\n// Lists the wallet's Lens accounts to sign in with, or the form to create one. Opens by itself when a\n// wallet connects without a Lens session, and can't be dismissed until an account is signed in to (or\n// the wallet disconnects). A dialog on desktop, a drawer on mobile.\nexport function AccountDialog() {\n const { wallet, signOut } = useLensAuth()\n const { open, required, setOpen } = useAccountDialogState()\n const isDesktop = useMediaQuery(\"(min-width: 768px)\")\n const [creating, setCreating] = React.useState(false)\n\n // Show the account list again the next time the dialog opens\n React.useEffect(() => {\n if (!open) setCreating(false)\n }, [open])\n\n const handleOpenChange = (next: boolean) => {\n if (!next && required) return\n setOpen(next)\n }\n\n const body = wallet\n ? <AccountDialogBody key={wallet.address} wallet={wallet} creating={creating} setCreating={setCreating} />\n : null\n const disconnect = (\n <Button onClick={signOut} variant=\"outline\" className=\"w-full\">\n Disconnect Wallet\n </Button>\n )\n\n if (isDesktop) {\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogContent\n className=\"sm:max-w-[425px] max-h-[80vh] overflow-y-auto\"\n showCloseButton={!required}\n onEscapeKeyDown={(e) => required && e.preventDefault()}\n onPointerDownOutside={(e) => required && e.preventDefault()}\n >\n {body}\n <div className=\"mt-4\">{disconnect}</div>\n </DialogContent>\n </Dialog>\n )\n }\n\n return (\n <Drawer open={open} onOpenChange={handleOpenChange} dismissible={!required}>\n <DrawerContent className=\"max-h-[80vh] overflow-y-auto\">\n {body}\n <div className=\"p-4\">{disconnect}</div>\n </DrawerContent>\n </Drawer>\n )\n}\n\nfunction AccountDialogBody({ wallet, creating, setCreating }: {\n wallet: ThirdwebAccount\n creating: boolean\n setCreating: (creating: boolean) => void\n}) {\n const { auth } = useLensAuth()\n const { completeSignIn } = useAccountDialogState()\n const isDesktop = useMediaQuery(\"(min-width: 768px)\")\n const { data, loading } = useAccountsAvailable({ managedBy: evmAddress(wallet.address), includeOwned: true })\n const accounts = data?.items\n // Accounts without a username aren't listed, so they don't count\n const hasAccounts = !!accounts?.some((item) => item.account.username?.localName)\n // Wallets without an account go straight to creating one\n const showCreate = creating || (!loading && !hasAccounts)\n\n const signIn = async (account: SelectableAccount, challenge: LensChallenge) => {\n // The signature request goes out before the first await, so a click handler calling this keeps its\n // user gesture, which mobile wallets need to open (see signLensChallenge).\n const signature = await auth.signChallenge(challenge, wallet)\n await auth.authenticate(challenge, signature)\n completeSignIn({ address: account.address.toLowerCase(), username: account.username?.localName ?? null })\n }\n\n const handleCreated = async (created: CreatedAccount) => {\n completeSignIn({ address: created.address.toLowerCase(), username: created.localName })\n }\n\n const title = showCreate ? \"Create Account\" : \"Select Account\"\n const description = showCreate\n ? hasAccounts ? \"Pick a username for your new Lens account.\" : \"You don’t have a Lens account yet. Create one to continue.\"\n : \"Select an account to continue.\"\n\n const Header = isDesktop ? DialogHeader : DrawerHeader\n const Title = isDesktop ? DialogTitle : DrawerTitle\n const Description = isDesktop ? DialogDescription : DrawerDescription\n\n return (\n <>\n <Header className={isDesktop ? undefined : \"text-left\"}>\n <Title>{title}</Title>\n <Description>{description}</Description>\n </Header>\n <div className={isDesktop || !showCreate ? undefined : \"px-4\"}>\n {showCreate ? (\n <CreateAccountForm\n ownerAddress={wallet.address}\n onCreated={handleCreated}\n onBack={hasAccounts ? () => setCreating(false) : undefined}\n />\n ) : (\n <AccountList auth={auth} accounts={accounts} loading={loading} ownerAddress={wallet.address} onSign={signIn} onCreate={() => setCreating(true)} />\n )}\n </div>\n </>\n )\n}\n\ntype SelectableAccount = Account & { isOwner: boolean }\n\ntype SignInStep =\n | { id: string; status: \"loading\" }\n | { id: string; status: \"sign\"; challenge: LensChallenge }\n\ntype PrefetchedChallenge = { owner: string; challenge: LensChallenge; fetchedAt: number }\n\nfunction fetchChallenge(auth: LensAuth, acc: SelectableAccount, ownerAddress: string) {\n return auth.requestChallenge({\n role: acc.isOwner ? \"ACCOUNT_OWNER\" : \"ACCOUNT_MANAGER\",\n account: acc.address,\n signer: ownerAddress,\n })\n}\n\nfunction AccountList({ auth, accounts, loading, ownerAddress, onSign, onCreate }: {\n auth: LensAuth\n accounts?: readonly AccountAvailable[]\n loading: boolean\n ownerAddress: string\n onSign: (account: SelectableAccount, challenge: LensChallenge) => Promise<void>\n onCreate: () => void\n}) {\n const [step, setStep] = React.useState<SignInStep | null>(null)\n const [errorId, setErrorId] = React.useState<string | null>(null)\n const [challenges, setChallenges] = React.useState<Record<string, PrefetchedChallenge>>({})\n\n const selectable = React.useMemo(() => (accounts ?? []).map((item, index) => {\n const acc: SelectableAccount = { ...item.account, isOwner: item.__typename === \"AccountOwned\" }\n return { acc, id: `${acc.address}-${index}` }\n }), [accounts])\n\n const prefetch = React.useCallback((acc: SelectableAccount, id: string) => {\n fetchChallenge(auth, acc, ownerAddress)\n .then((challenge) => setChallenges((prev) => ({ ...prev, [id]: { owner: ownerAddress, challenge, fetchedAt: Date.now() } })))\n .catch(() => {})\n }, [auth, ownerAddress])\n\n // Fetch each account's challenge ahead of time, so a tap can ask the wallet to sign right away:\n // on mobile that tap is what lets the wallet app open (see opensWalletWithDeepLink).\n React.useEffect(() => {\n const refresh = () => {\n if (document.visibilityState !== \"visible\") return\n for (const { acc, id } of selectable) {\n if (acc.username?.localName) prefetch(acc, id)\n }\n }\n refresh()\n const interval = setInterval(refresh, CHALLENGE_REFRESH_MS)\n document.addEventListener(\"visibilitychange\", refresh)\n return () => {\n clearInterval(interval)\n document.removeEventListener(\"visibilitychange\", refresh)\n }\n }, [selectable, prefetch])\n\n const readyChallenge = (id: string) => {\n if (step?.id === id && step.status === \"sign\") return step.challenge\n const prefetched = challenges[id]\n if (!prefetched || prefetched.owner !== ownerAddress) return null\n return Date.now() - prefetched.fetchedAt < CHALLENGE_MAX_AGE_MS ? prefetched.challenge : null\n }\n\n const handleClick = (acc: SelectableAccount, id: string) => {\n setErrorId(null)\n const fail = () => {\n setStep(null)\n setErrorId(id)\n prefetch(acc, id)\n }\n const challenge = readyChallenge(id)\n if (challenge) {\n // Sign now, while the tap still counts as a user gesture. A challenge can only be used once.\n const signing = onSign(acc, challenge)\n setChallenges(({ [id]: _used, ...rest }) => rest)\n setStep({ id, status: \"loading\" })\n signing.then(() => setStep(null), fail)\n return\n }\n // The challenge isn't ready yet: fetch it now. Desktop wallets sign without a user gesture;\n // on mobile it takes one more tap to open the wallet.\n setStep({ id, status: \"loading\" })\n ;(async () => {\n const fetched = await fetchChallenge(auth, acc, ownerAddress)\n if (opensWalletWithDeepLink()) return setStep({ id, status: \"sign\", challenge: fetched })\n await onSign(acc, fetched)\n setStep(null)\n })().catch(fail)\n }\n\n if (loading) {\n return (\n <div className=\"p-4\">\n <p className=\"text-sm text-muted-foreground\">Loading available profiles…</p>\n </div>\n )\n }\n\n return (\n <div className=\"py-4 space-y-3\">\n <ul className=\"space-y-2 max-h-80 overflow-y-auto\">\n {selectable.map(({ acc, id }) => {\n const username = acc.username?.localName\n if (!username) return null\n const isLoading = step?.id === id && step.status === \"loading\"\n const awaitingSignature = step?.id === id && step.status === \"sign\"\n return (\n <li key={id}>\n <button\n type=\"button\"\n className=\"w-full text-left px-3 py-2 rounded-md border hover:bg-accent/50 flex items-center justify-between cursor-pointer disabled:cursor-default\"\n onClick={() => handleClick(acc, id)}\n disabled={step?.status === \"loading\"}\n >\n <span className=\"truncate\">{username}</span>\n {isLoading && <Loader2 className=\"size-4 animate-spin text-muted-foreground\" />}\n {awaitingSignature && <span className=\"text-sm font-medium text-primary\">Sign in</span>}\n </button>\n {awaitingSignature && (\n <p className=\"px-1 pt-1 text-xs text-muted-foreground\">Tap again to sign the message in your wallet.</p>\n )}\n {errorId === id && (\n <p className=\"px-1 pt-1 text-xs text-destructive\">Couldn’t sign in. Please try again.</p>\n )}\n </li>\n )\n })}\n </ul>\n <Button variant=\"ghost\" className=\"w-full\" onClick={onCreate} disabled={step?.status === \"loading\"}>\n Create a new account\n </Button>\n </div>\n )\n}\n","import * as React from \"react\"\nimport { useActiveAccount, useActiveWallet } from \"thirdweb/react\"\nimport type { SessionClient } from \"@lens-protocol/client\"\nimport { Check, Loader2 } from \"lucide-react\"\nimport { CHALLENGE_MAX_AGE_MS, CHALLENGE_REFRESH_MS, opensWalletWithDeepLink, signLensChallenge, type LensChallenge } from \"../core/auth\"\nimport {\n OnboardingError,\n authenticateOnboarding,\n checkUsername,\n createLensAccount,\n createOnboardingClient,\n isUsernameTaken,\n requestOnboardingChallenge,\n signInToCreatedAccount,\n uploadAccountMetadata,\n usernameFormatError,\n} from \"../core/onboarding\"\nimport { useLensAuth } from \"./provider\"\nimport { cn } from \"./utils\"\nimport { Button } from \"./ui/button\"\nimport { Input } from \"./ui/input\"\nimport { Textarea } from \"./ui/textarea\"\nimport { Avatar, AvatarFallback, AvatarImage } from \"./ui/avatar\"\nimport { Field, FieldContent, FieldDescription, FieldGroup, FieldLabel } from \"./ui/field\"\nimport { InputGroup, InputGroupAddon, InputGroupInput, InputGroupText } from \"./ui/input-group\"\n\nexport type CreatedAccount = { address: string; localName: string }\n\ntype Step =\n | { status: \"signing\" }\n // The challenge arrived after the tap: on mobile it takes one more tap to open the wallet\n | { status: \"sign\"; challenge: LensChallenge }\n | { status: \"checking\" | \"uploading\" | \"creating\" | \"signing-in\" }\n\nconst STEP_LABELS = {\n signing: \"Waiting for signature…\",\n sign: \"Sign in wallet\",\n checking: \"Checking username…\",\n uploading: \"Uploading profile…\",\n creating: \"Creating account…\",\n \"signing-in\": \"Signing in…\",\n} satisfies Record<Step[\"status\"], string>\n\ntype Availability = { localName: string; status: \"checking\" | \"available\" | \"taken\" | \"unknown\" }\n\n// Same delay as the search on the find page\nconst USERNAME_DEBOUNCE_MS = 300\nconst MAX_PICTURE_BYTES = 10 * 1024 * 1024\n\n// Render with `key={ownerAddress}`: the onboarding session belongs to the wallet that signed it.\nexport function CreateAccountForm({ ownerAddress, onCreated, onBack }: {\n ownerAddress: string\n onCreated: (account: CreatedAccount) => Promise<void>\n onBack?: () => void\n}) {\n const { auth } = useLensAuth()\n const activeAccount = useActiveAccount()\n const wallet = useActiveWallet()\n\n const [client] = React.useState(() => createOnboardingClient(auth))\n // Kept across attempts so a retry doesn't ask for another signature or create a second account\n const session = React.useRef<SessionClient | null>(null)\n const created = React.useRef<CreatedAccount | null>(null)\n const pictureInput = React.useRef<HTMLInputElement>(null)\n\n const [username, setUsername] = React.useState(\"\")\n const [debouncedUsername, setDebouncedUsername] = React.useState(\"\")\n const [name, setName] = React.useState(\"\")\n const [bio, setBio] = React.useState(\"\")\n const [picture, setPicture] = React.useState<File | null>(null)\n const [pictureUrl, setPictureUrl] = React.useState<string | null>(null)\n\n const [availability, setAvailability] = React.useState<Availability | null>(null)\n const [usernameError, setUsernameError] = React.useState<{ localName: string; message: string } | null>(null)\n const [step, setStep] = React.useState<Step | null>(null)\n const [error, setError] = React.useState<string | null>(null)\n const [prefetched, setPrefetched] = React.useState<{ challenge: LensChallenge; fetchedAt: number } | null>(null)\n\n const formatError = username ? usernameFormatError(username) : null\n const busy = step !== null && step.status !== \"sign\"\n\n // Fetch the challenge ahead of time, so the tap on \"Create account\" can ask the wallet to sign right\n // away: on mobile that tap is what lets the wallet app open (see opensWalletWithDeepLink).\n React.useEffect(() => {\n const refresh = () => {\n if (document.visibilityState !== \"visible\" || session.current) return\n requestOnboardingChallenge(auth, client, ownerAddress)\n .then((challenge) => setPrefetched({ challenge, fetchedAt: Date.now() }))\n .catch(() => {})\n }\n refresh()\n const interval = setInterval(refresh, CHALLENGE_REFRESH_MS)\n document.addEventListener(\"visibilitychange\", refresh)\n return () => {\n clearInterval(interval)\n document.removeEventListener(\"visibilitychange\", refresh)\n }\n }, [auth, client, ownerAddress])\n\n // End the onboarding session if the form is left before the account is signed in to\n React.useEffect(() => () => {\n if (!created.current) void session.current?.logout()\n }, [])\n\n React.useEffect(() => {\n if (!picture) return setPictureUrl(null)\n const url = URL.createObjectURL(picture)\n setPictureUrl(url)\n return () => URL.revokeObjectURL(url)\n }, [picture])\n\n // Only check the username once typing pauses, not on every keystroke\n React.useEffect(() => {\n const timeout = setTimeout(() => setDebouncedUsername(username), USERNAME_DEBOUNCE_MS)\n return () => clearTimeout(timeout)\n }, [username])\n\n React.useEffect(() => {\n if (!debouncedUsername || usernameFormatError(debouncedUsername)) return\n let cancelled = false\n setAvailability({ localName: debouncedUsername, status: \"checking\" })\n isUsernameTaken(auth, debouncedUsername)\n .then((taken) => !cancelled && setAvailability({ localName: debouncedUsername, status: taken ? \"taken\" : \"available\" }))\n .catch(() => !cancelled && setAvailability({ localName: debouncedUsername, status: \"unknown\" }))\n return () => {\n cancelled = true\n }\n }, [auth, debouncedUsername])\n\n const fail = (e: unknown) => {\n setStep(null)\n if ((e as Error)?.name === \"UnauthenticatedError\") session.current = null\n setError(e instanceof OnboardingError ? e.message : \"Couldn’t create your account. Please try again.\")\n }\n\n const create = async (onboarding: SessionClient) => {\n const localName = username\n if (!created.current) {\n setStep({ status: \"checking\" })\n const reason = await checkUsername(onboarding, localName)\n if (reason) {\n setUsernameError({ localName, message: reason })\n setStep(null)\n return\n }\n setStep({ status: \"uploading\" })\n const metadataUri = await uploadAccountMetadata(auth, { name: name.trim(), bio: bio.trim(), picture })\n setStep({ status: \"creating\" })\n if (!wallet) throw new OnboardingError(\"Connect your wallet\")\n const account = await createLensAccount(auth, onboarding, wallet, { localName, metadataUri })\n created.current = { address: account.address, localName: account.username?.localName ?? localName }\n }\n setStep({ status: \"signing-in\" })\n await signInToCreatedAccount(auth, onboarding, created.current.address)\n await onCreated(created.current)\n }\n\n const continueWith = (authenticating: Promise<SessionClient | null>) => {\n authenticating\n .then(async (onboarding) => {\n if (!onboarding) return\n session.current = onboarding\n await create(onboarding)\n })\n .catch(fail)\n }\n\n const readyChallenge = () => {\n if (step?.status === \"sign\") return step.challenge\n if (!prefetched || Date.now() - prefetched.fetchedAt >= CHALLENGE_MAX_AGE_MS) return null\n return prefetched.challenge\n }\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault()\n if (busy || !activeAccount) return\n if (!username) return setUsernameError({ localName: username, message: \"Choose a username\" })\n if (formatError || availability?.status === \"taken\") return\n setError(null)\n setUsernameError(null)\n\n if (session.current) {\n setStep({ status: \"checking\" })\n create(session.current).catch(fail)\n return\n }\n\n const challenge = readyChallenge()\n if (challenge) {\n // Sign now, while the tap still counts as a user gesture. A challenge can only be used once.\n const signing = signLensChallenge(challenge, activeAccount)\n setPrefetched(null)\n setStep({ status: \"signing\" })\n continueWith(signing.then((signature) => authenticateOnboarding(client, challenge, signature)))\n return\n }\n\n // The challenge isn't ready yet: fetch it now. Desktop wallets sign without a user gesture;\n // on mobile it takes one more tap to open the wallet.\n setStep({ status: \"signing\" })\n continueWith((async () => {\n const fetched = await requestOnboardingChallenge(auth, client, ownerAddress)\n if (opensWalletWithDeepLink()) {\n setStep({ status: \"sign\", challenge: fetched })\n return null\n }\n const signature = await signLensChallenge(fetched, activeAccount)\n return authenticateOnboarding(client, fetched, signature)\n })())\n }\n\n const handlePictureChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0] ?? null\n e.target.value = \"\"\n if (file && file.size > MAX_PICTURE_BYTES) return setError(\"Choose a picture under 10 MB\")\n setError(null)\n setPicture(file)\n }\n\n const usernameMessage = (() => {\n if (formatError) return { text: formatError, isError: true }\n if (usernameError?.localName === username) return { text: usernameError.message, isError: true }\n if (availability?.localName !== username) return null\n switch (availability.status) {\n case \"checking\": return { text: \"Checking availability…\", isError: false }\n case \"available\": return { text: \"Available\", isError: false }\n case \"taken\": return { text: \"This username is taken\", isError: true }\n default: return null\n }\n })()\n\n const fallbackInitial = (name.trim() || username || \"?\").charAt(0).toUpperCase()\n const usernameStatus = availability?.localName === username && !formatError ? availability.status : null\n\n return (\n <form className=\"py-4\" onSubmit={handleSubmit} noValidate>\n <FieldGroup className=\"gap-5\">\n <Field orientation=\"horizontal\">\n <Avatar className=\"size-16\">\n {pictureUrl && <AvatarImage src={pictureUrl} alt=\"\" className=\"object-cover\" />}\n <AvatarFallback className=\"text-lg font-semibold\">{fallbackInitial}</AvatarFallback>\n </Avatar>\n <FieldContent>\n <FieldLabel htmlFor=\"create-account-picture\">\n Profile picture <span className=\"font-normal text-muted-foreground\">(optional)</span>\n </FieldLabel>\n <div className=\"flex gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => pictureInput.current?.click()} disabled={busy}>\n {picture ? \"Change\" : \"Add photo\"}\n </Button>\n {picture && (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={() => setPicture(null)} disabled={busy}>\n Remove\n </Button>\n )}\n </div>\n </FieldContent>\n <input\n ref={pictureInput}\n id=\"create-account-picture\"\n type=\"file\"\n accept=\"image/*\"\n className=\"sr-only\"\n onChange={handlePictureChange}\n disabled={busy}\n />\n </Field>\n\n <Field data-invalid={usernameMessage?.isError || undefined}>\n <FieldLabel htmlFor=\"create-account-username\">Username</FieldLabel>\n <InputGroup>\n <InputGroupAddon>\n <InputGroupText>@</InputGroupText>\n </InputGroupAddon>\n <InputGroupInput\n id=\"create-account-username\"\n value={username}\n onChange={(e) => setUsername(e.target.value.trim().toLowerCase())}\n autoComplete=\"off\"\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n spellCheck={false}\n aria-invalid={usernameMessage?.isError || undefined}\n aria-describedby=\"create-account-username-status\"\n disabled={busy}\n />\n <InputGroupAddon align=\"inline-end\">\n {usernameStatus === \"checking\" && <Loader2 className=\"animate-spin\" />}\n {usernameStatus === \"available\" && <Check />}\n </InputGroupAddon>\n </InputGroup>\n {/* Always rendered with a fixed height, so the form doesn't shift as the feedback changes */}\n <FieldDescription\n id=\"create-account-username-status\"\n aria-live=\"polite\"\n className={cn(\"min-h-5 leading-5\", usernameMessage?.isError && \"text-destructive\")}\n >\n {usernameMessage?.text}\n </FieldDescription>\n </Field>\n\n <Field>\n <FieldLabel htmlFor=\"create-account-name\">\n Name <span className=\"font-normal text-muted-foreground\">(optional)</span>\n </FieldLabel>\n <Input id=\"create-account-name\" value={name} onChange={(e) => setName(e.target.value)} maxLength={100} disabled={busy} />\n </Field>\n\n <Field>\n <FieldLabel htmlFor=\"create-account-bio\">\n Bio <span className=\"font-normal text-muted-foreground\">(optional)</span>\n </FieldLabel>\n <Textarea\n id=\"create-account-bio\"\n value={bio}\n onChange={(e) => setBio(e.target.value)}\n maxLength={300}\n rows={3}\n className=\"resize-none\"\n disabled={busy}\n />\n </Field>\n\n <Field className=\"gap-2\">\n <Button type=\"submit\" className=\"w-full\" disabled={busy || !activeAccount}>\n {busy && <Loader2 className=\"animate-spin\" />}\n {step ? STEP_LABELS[step.status] : \"Create account\"}\n </Button>\n <FieldDescription aria-live=\"polite\" className={cn(\"min-h-5 leading-5\", error && \"text-destructive\")}>\n {error ?? (step?.status === \"sign\" ? \"Tap again to sign in your wallet.\" : \"You’ll sign a message in your wallet. It’s free.\")}\n </FieldDescription>\n {onBack && (\n <Button type=\"button\" variant=\"ghost\" className=\"w-full\" onClick={onBack} disabled={busy}>\n Back to your accounts\n </Button>\n )}\n </Field>\n </FieldGroup>\n </form>\n )\n}\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../utils\"\n\nconst buttonVariants = cva(\n \"cursor-pointer inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n xl: \"h-[50px] rounded-md px-8 has-[>svg]:px-6\",\n icon: \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","import * as React from \"react\"\n\nimport { cn } from \"../utils\"\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n \"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n \"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n \"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Input }\n","import * as React from \"react\"\nimport { cn } from \"../utils\"\n\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n \"flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:ring-destructive/40\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Textarea }\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as AvatarPrimitive from \"@radix-ui/react-avatar\"\n\nimport { cn } from \"../utils\"\n\nfunction Avatar({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Root>) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n className={cn(\n \"relative flex size-8 shrink-0 overflow-hidden rounded-full\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarImage({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\"aspect-square size-full\", className)}\n {...props}\n />\n )\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"bg-muted flex size-full items-center justify-center rounded-full\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Avatar, AvatarImage, AvatarFallback }\n","\"use client\"\n\nimport { useMemo } from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"../utils\"\n\nimport { Label } from \"./label\"\nimport { Separator } from \"./separator\"\n\nfunction FieldSet({ className, ...props }: React.ComponentProps<\"fieldset\">) {\n return (\n <fieldset\n data-slot=\"field-set\"\n className={cn(\n \"flex flex-col gap-6\",\n \"has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldLegend({\n className,\n variant = \"legend\",\n ...props\n}: React.ComponentProps<\"legend\"> & { variant?: \"legend\" | \"label\" }) {\n return (\n <legend\n data-slot=\"field-legend\"\n data-variant={variant}\n className={cn(\n \"mb-3 font-medium\",\n \"data-[variant=legend]:text-base\",\n \"data-[variant=label]:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-group\"\n className={cn(\n \"group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nconst fieldVariants = cva(\n \"group/field flex w-full gap-3 data-[invalid=true]:text-destructive\",\n {\n variants: {\n orientation: {\n vertical: [\"flex-col [&>*]:w-full [&>.sr-only]:w-auto\"],\n horizontal: [\n \"flex-row items-center\",\n \"[&>[data-slot=field-label]]:flex-auto\",\n \"has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px\",\n ],\n responsive: [\n \"flex-col @md/field-group:flex-row @md/field-group:items-center [&>*]:w-full @md/field-group:[&>*]:w-auto [&>.sr-only]:w-auto\",\n \"@md/field-group:[&>[data-slot=field-label]]:flex-auto\",\n \"@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px\",\n ],\n },\n },\n defaultVariants: {\n orientation: \"vertical\",\n },\n }\n)\n\nfunction Field({\n className,\n orientation = \"vertical\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof fieldVariants>) {\n return (\n <div\n role=\"group\"\n data-slot=\"field\"\n data-orientation={orientation}\n className={cn(fieldVariants({ orientation }), className)}\n {...props}\n />\n )\n}\n\nfunction FieldContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-content\"\n className={cn(\n \"group/field-content flex flex-1 flex-col gap-1.5 leading-snug\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldLabel({\n className,\n ...props\n}: React.ComponentProps<typeof Label>) {\n return (\n <Label\n data-slot=\"field-label\"\n className={cn(\n \"group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50\",\n \"has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-4\",\n \"has-data-[state=checked]:border-primary has-data-[state=checked]:bg-primary/5 dark:has-data-[state=checked]:bg-primary/10\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-label\"\n className={cn(\n \"flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n <p\n data-slot=\"field-description\"\n className={cn(\n \"text-sm leading-normal font-normal text-muted-foreground group-has-[[data-orientation=horizontal]]/field:text-balance\",\n \"last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5\",\n \"[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldSeparator({\n children,\n className,\n ...props\n}: React.ComponentProps<\"div\"> & {\n children?: React.ReactNode\n}) {\n return (\n <div\n data-slot=\"field-separator\"\n data-content={!!children}\n className={cn(\n \"relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2\",\n className\n )}\n {...props}\n >\n <Separator className=\"absolute inset-0 top-1/2\" />\n {children && (\n <span\n className=\"relative mx-auto block w-fit bg-background px-2 text-muted-foreground\"\n data-slot=\"field-separator-content\"\n >\n {children}\n </span>\n )}\n </div>\n )\n}\n\nfunction FieldError({\n className,\n children,\n errors,\n ...props\n}: React.ComponentProps<\"div\"> & {\n errors?: Array<{ message?: string } | undefined>\n}) {\n const content = useMemo(() => {\n if (children) {\n return children\n }\n\n if (!errors?.length) {\n return null\n }\n\n const uniqueErrors = [\n ...new Map(errors.map((error) => [error?.message, error])).values(),\n ]\n\n if (uniqueErrors?.length == 1) {\n return uniqueErrors[0]?.message\n }\n\n return (\n <ul className=\"ml-4 flex list-disc flex-col gap-1\">\n {uniqueErrors.map(\n (error, index) =>\n error?.message && <li key={index}>{error.message}</li>\n )}\n </ul>\n )\n }, [children, errors])\n\n if (!content) {\n return null\n }\n\n return (\n <div\n role=\"alert\"\n data-slot=\"field-error\"\n className={cn(\"text-sm font-normal text-destructive\", className)}\n {...props}\n >\n {content}\n </div>\n )\n}\n\nexport {\n Field,\n FieldLabel,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLegend,\n FieldSeparator,\n FieldSet,\n FieldContent,\n FieldTitle,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"../utils\"\nimport * as LabelPrimitive from \"@radix-ui/react-label\"\n\nfunction Label({\n className,\n ...props\n}: React.ComponentProps<typeof LabelPrimitive.Root>) {\n return (\n <LabelPrimitive.Root\n data-slot=\"label\"\n className={cn(\n \"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Label }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"../utils\"\n\nimport { Button } from \"./button\"\nimport { Input } from \"./input\"\nimport { Textarea } from \"./textarea\"\n\nfunction InputGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"input-group\"\n role=\"group\"\n className={cn(\n \"group/input-group relative flex w-full items-center rounded-md border border-input shadow-xs transition-[color,box-shadow] outline-none dark:bg-input/30\",\n \"h-9 min-w-0 has-[>textarea]:h-auto\",\n\n // Variants based on alignment.\n \"has-[>[data-align=inline-start]]:[&>input]:pl-2\",\n \"has-[>[data-align=inline-end]]:[&>input]:pr-2\",\n \"has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3\",\n \"has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3\",\n\n // Focus state.\n \"has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-[3px] has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50\",\n\n // Error state.\n \"has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-destructive/20 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40\",\n\n className\n )}\n {...props}\n />\n )\n}\n\nconst inputGroupAddonVariants = cva(\n \"flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n align: {\n \"inline-start\":\n \"order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]\",\n \"inline-end\":\n \"order-last pr-3 has-[>button]:mr-[-0.45rem] has-[>kbd]:mr-[-0.35rem]\",\n \"block-start\":\n \"order-first w-full justify-start px-3 pt-3 group-has-[>input]/input-group:pt-2.5 [.border-b]:pb-3\",\n \"block-end\":\n \"order-last w-full justify-start px-3 pb-3 group-has-[>input]/input-group:pb-2.5 [.border-t]:pt-3\",\n },\n },\n defaultVariants: {\n align: \"inline-start\",\n },\n }\n)\n\nfunction InputGroupAddon({\n className,\n align = \"inline-start\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof inputGroupAddonVariants>) {\n return (\n <div\n role=\"group\"\n data-slot=\"input-group-addon\"\n data-align={align}\n className={cn(inputGroupAddonVariants({ align }), className)}\n onClick={(e) => {\n if ((e.target as HTMLElement).closest(\"button\")) {\n return\n }\n e.currentTarget.parentElement?.querySelector(\"input\")?.focus()\n }}\n {...props}\n />\n )\n}\n\nconst inputGroupButtonVariants = cva(\n \"flex items-center gap-2 text-sm shadow-none\",\n {\n variants: {\n size: {\n xs: \"h-6 gap-1 rounded-[calc(var(--radius)-5px)] px-2 has-[>svg]:px-2 [&>svg:not([class*='size-'])]:size-3.5\",\n sm: \"h-8 gap-1.5 rounded-md px-2.5 has-[>svg]:px-2.5\",\n \"icon-xs\":\n \"size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0\",\n \"icon-sm\": \"size-8 p-0 has-[>svg]:p-0\",\n },\n },\n defaultVariants: {\n size: \"xs\",\n },\n }\n)\n\nfunction InputGroupButton({\n className,\n type = \"button\",\n variant = \"ghost\",\n size = \"xs\",\n ...props\n}: Omit<React.ComponentProps<typeof Button>, \"size\"> &\n VariantProps<typeof inputGroupButtonVariants>) {\n return (\n <Button\n type={type}\n data-size={size}\n variant={variant}\n className={cn(inputGroupButtonVariants({ size }), className)}\n {...props}\n />\n )\n}\n\nfunction InputGroupText({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n className={cn(\n \"flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction InputGroupInput({\n className,\n ...props\n}: React.ComponentProps<\"input\">) {\n return (\n <Input\n data-slot=\"input-group-control\"\n className={cn(\n \"flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction InputGroupTextarea({\n className,\n ...props\n}: React.ComponentProps<\"textarea\">) {\n return (\n <Textarea\n data-slot=\"input-group-control\"\n className={cn(\n \"flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n InputGroup,\n InputGroupAddon,\n InputGroupButton,\n InputGroupText,\n InputGroupInput,\n InputGroupTextarea,\n}\n","import * as React from \"react\"\n\nexport function useMediaQuery(query: string): boolean {\n return React.useSyncExternalStore(\n (onChange) => {\n const media = window.matchMedia(query)\n media.addEventListener(\"change\", onChange)\n return () => media.removeEventListener(\"change\", onChange)\n },\n () => window.matchMedia(query).matches,\n () => false,\n )\n}\n\n// The page's theme: a `dark` or `light` class on <html> (as next-themes and shadcn set it), otherwise\n// the system preference.\nfunction readTheme(): \"light\" | \"dark\" {\n const classes = document.documentElement.classList\n if (classes.contains(\"dark\")) return \"dark\"\n if (classes.contains(\"light\")) return \"light\"\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\"\n}\n\nexport function useDocumentTheme(): \"light\" | \"dark\" {\n return React.useSyncExternalStore(\n (onChange) => {\n const observer = new MutationObserver(onChange)\n observer.observe(document.documentElement, { attributes: true, attributeFilter: [\"class\"] })\n const media = window.matchMedia(\"(prefers-color-scheme: dark)\")\n media.addEventListener(\"change\", onChange)\n return () => {\n observer.disconnect()\n media.removeEventListener(\"change\", onChange)\n }\n },\n readTheme,\n () => \"light\",\n )\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\"\nimport { XIcon } from \"lucide-react\"\n\nimport { cn } from \"../utils\"\n\nfunction Dialog({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />\n}\n\nfunction DialogTrigger({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />\n}\n\nfunction DialogPortal({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />\n}\n\nfunction DialogClose({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content> & {\n showCloseButton?: boolean\n}) {\n return (\n <DialogPortal data-slot=\"dialog-portal\">\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n \"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\"\n >\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-lg leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"../utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Root>) {\n return <DrawerPrimitive.Root data-slot=\"drawer\" {...props} />\n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {\n return <DrawerPrimitive.Trigger data-slot=\"drawer-trigger\" {...props} />\n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Portal>) {\n return <DrawerPrimitive.Portal data-slot=\"drawer-portal\" {...props} />\n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Close>) {\n return <DrawerPrimitive.Close data-slot=\"drawer-close\" {...props} />\n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {\n return (\n <DrawerPrimitive.Overlay\n data-slot=\"drawer-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Content>) {\n return (\n <DrawerPortal data-slot=\"drawer-portal\">\n <DrawerOverlay />\n <DrawerPrimitive.Content\n data-slot=\"drawer-content\"\n className={cn(\n \"group/drawer-content bg-background fixed z-50 flex h-auto flex-col\",\n \"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b\",\n \"data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t\",\n \"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm\",\n \"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm\",\n className\n )}\n {...props}\n >\n <div className=\"bg-muted mx-auto mt-4 hidden h-2 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block\" />\n {children}\n </DrawerPrimitive.Content>\n </DrawerPortal>\n )\n}\n\nfunction DrawerHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"drawer-header\"\n className={cn(\n \"flex flex-col gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-1.5 md:text-left\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DrawerFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"drawer-footer\"\n className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Title>) {\n return (\n <DrawerPrimitive.Title\n data-slot=\"drawer-title\"\n className={cn(\"text-foreground font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Description>) {\n return (\n <DrawerPrimitive.Description\n data-slot=\"drawer-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Drawer,\n DrawerPortal,\n DrawerOverlay,\n DrawerTrigger,\n DrawerClose,\n DrawerContent,\n DrawerHeader,\n DrawerFooter,\n DrawerTitle,\n DrawerDescription,\n}\n","import * as React from \"react\"\nimport type { ConnectButtonProps } from \"thirdweb/react\"\nimport { useLensAuth } from \"./provider\"\nimport { useDocumentTheme } from \"./dom\"\nimport { Button } from \"./ui/button\"\nimport { cn } from \"./utils\"\n\n// thirdweb's ConnectButton pulls in ~480KB (gzipped) of wallet SDKs (WalletConnect, Coinbase, ...).\n// Loading it on demand keeps that out of every page's initial bundle, so pages hydrate without\n// waiting for it.\nconst ConnectButton = React.lazy(() => import(\"thirdweb/react\").then((m) => ({ default: m.ConnectButton })))\n\nexport type SignInButtonProps = {\n /** Defaults to \"Sign in\" */\n label?: React.ReactNode\n /** Defaults to \"Logout\" */\n signOutLabel?: React.ReactNode\n /** thirdweb modal theme. Defaults to the page's theme (a `dark` class on <html>, or the system's). */\n theme?: \"light\" | \"dark\"\n /** Classes for the placeholder and sign-out buttons. Size the button's wrapper to size them all alike. */\n className?: string\n /** Extra props for thirdweb's ConnectButton (wallets, connectModal, ...) */\n connectButtonProps?: Partial<Omit<ConnectButtonProps, \"client\" | \"chain\" | \"theme\">>\n}\n\n// Connects a wallet (the account dialog then opens to pick or create a Lens account) and signs out.\nexport function SignInButton({ label = \"Sign in\", signOutLabel = \"Logout\", theme, className, connectButtonProps }: SignInButtonProps) {\n const { auth, wallet, status, signOut } = useLensAuth()\n const documentTheme = useDocumentTheme()\n const [mounted, setMounted] = React.useState(false)\n React.useEffect(() => setMounted(true), [])\n\n // Same size as the real button, so nothing shifts when it loads\n const placeholder = (\n <Button variant=\"outline\" size=\"xl\" className={cn(\"min-w-[165px] px-0\", className)} disabled>\n Loading...\n </Button>\n )\n\n // thirdweb's ConnectButton doesn't render the same on the server and the client\n if (!mounted) return placeholder\n\n if (!wallet) {\n return (\n <React.Suspense fallback={placeholder}>\n <ConnectButton\n client={auth.thirdwebClient}\n chain={auth.chain}\n theme={theme ?? documentTheme}\n {...connectButtonProps}\n connectButton={{\n label,\n ...connectButtonProps?.connectButton,\n style: { height: \"50px\", minWidth: \"165px\", ...connectButtonProps?.connectButton?.style },\n }}\n />\n </React.Suspense>\n )\n }\n\n if (status !== \"signed-in\") return placeholder\n\n return (\n <Button variant=\"ghost\" size=\"xl\" className={cn(\"min-w-[165px] px-0\", className)} onClick={signOut}>\n {signOutLabel}\n </Button>\n )\n}\n"],"mappings":"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","names":["React","useActiveAccount","useActiveWallet","React","Loader2","jsx","jsx","jsx","cva","jsx","jsx","jsx","cva","jsx","cva","jsx","cva","jsx","jsx","jsxs","React","jsx","jsxs","jsx","jsx","jsxs","jsx","jsx","jsxs","jsx","jsx","jsxs","jsx","jsx","jsxs","Title","Description","Loader2","jsx","jsxs","useActiveAccount","useActiveWallet","React","jsx"]}
1
+ {"version":3,"sources":["../../src/react/provider.tsx","../../src/react/AccountDialog.tsx","../../src/react/CreateAccountForm.tsx","../../src/react/utils.ts","../../src/react/ui/button.tsx","../../src/react/ui/input.tsx","../../src/react/ui/textarea.tsx","../../src/react/ui/avatar.tsx","../../src/react/ui/field.tsx","../../src/react/ui/label.tsx","../../src/react/ui/input-group.tsx","../../src/react/dom.ts","../../src/react/ui/dialog.tsx","../../src/react/ui/drawer.tsx","../../src/react/SignInButton.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { LensProvider } from \"@lens-protocol/react\"\nimport { ThirdwebProvider, useActiveAccount, useActiveWallet, useDisconnect } from \"thirdweb/react\"\nimport type { Account as ThirdwebAccount } from \"thirdweb/wallets\"\nimport { ConvexProviderWithAuth, useConvexAuth, type ConvexReactClient } from \"convex/react\"\nimport type { LensAuth } from \"../core/auth\"\nimport { TOKENS_CHANGED_EVENT } from \"../core/tokens\"\nimport { AccountDialog } from \"./AccountDialog\"\n\nexport type SignedInAccount = {\n /** Lens account address, lowercased */\n address: string\n /** Lens username (local name), when known */\n username: string | null\n}\n\nexport type LensAuthStatus =\n /** Reading the stored session (first render, and during SSR) */\n | \"loading\"\n /** No wallet and no Lens session */\n | \"signed-out\"\n /** Wallet connected, no Lens account signed in yet: the account dialog is open */\n | \"choosing-account\"\n /** Signed in to a Lens account (Convex is authenticated as it too) */\n | \"signed-in\"\n\nexport type LensAuthContextValue = {\n auth: LensAuth\n status: LensAuthStatus\n isLoading: boolean\n isSignedIn: boolean\n /** The connected thirdweb wallet account */\n wallet: ThirdwebAccount | undefined\n /** The signed-in Lens account */\n account: SignedInAccount | null\n /** Ends the Lens session and disconnects the wallet */\n signOut: () => Promise<void>\n /** Opens the account dialog, e.g. to switch to another account */\n openAccountDialog: () => void\n}\n\ntype AccountDialogState = {\n open: boolean\n // True while a wallet is connected without a Lens session: the dialog can't be dismissed\n required: boolean\n setOpen: (open: boolean) => void\n completeSignIn: (account: SignedInAccount) => void\n}\n\nconst LensAuthContext = React.createContext<LensAuthContextValue | null>(null)\nconst AccountDialogContext = React.createContext<AccountDialogState | null>(null)\n\nexport function useLensAuth(): LensAuthContextValue {\n const ctx = React.useContext(LensAuthContext)\n if (!ctx) throw new Error(\"useLensAuth must be used within <LensAuthProvider>\")\n return ctx\n}\n\nexport function useAccountDialogState(): AccountDialogState {\n const ctx = React.useContext(AccountDialogContext)\n if (!ctx) throw new Error(\"<AccountDialog> must be used within <LensAuthProvider>\")\n return ctx\n}\n\nfunction subscribeToTokens(onChange: () => void) {\n window.addEventListener(TOKENS_CHANGED_EVENT, onChange)\n // Signing in or out in another tab\n window.addEventListener(\"storage\", onChange)\n return () => {\n window.removeEventListener(TOKENS_CHANGED_EVENT, onChange)\n window.removeEventListener(\"storage\", onChange)\n }\n}\n\n// Identifies the stored Lens session: its id plus the account it acts for. Token refreshes keep it the\n// same; signing in again, or as another account, changes it. Undefined until read on the client.\nfunction useSessionKey(auth: LensAuth): string | null | undefined {\n return React.useSyncExternalStore(\n subscribeToTokens,\n () => {\n const session = auth.getSession()\n return session ? `${session.sessionId}:${session.account}` : null\n },\n () => undefined,\n )\n}\n\n// Signs Convex in as the Lens account the user signed in with. A new session gets a new\n// fetchAccessToken, which makes Convex fetch its token again.\nfunction createUseConvexAuth(auth: LensAuth) {\n return function useLensConvexAuth() {\n const sessionKey = useSessionKey(auth)\n const fetchAccessToken = React.useCallback(\n async ({ forceRefreshToken }: { forceRefreshToken: boolean }) =>\n sessionKey ? auth.fetchConvexToken(forceRefreshToken) : null,\n [sessionKey],\n )\n return { isLoading: sessionKey === undefined, isAuthenticated: !!sessionKey, fetchAccessToken }\n }\n}\n\nexport type LensAuthProviderProps = {\n /** From createLensAuth(), created once at module level */\n auth: LensAuth\n /** Your ConvexReactClient. Omit to use the package without Convex. */\n convex?: ConvexReactClient\n /**\n * Called after the user signs in from the account dialog (picking an account or creating one), once\n * Convex accepts the session. A good place to create the user's row: `convex.mutation(api.users.ensure)`\n */\n onSignIn?: (account: SignedInAccount) => void | Promise<void>\n /** Render the account dialog. Set to false to render <AccountDialog /> yourself. Defaults to true. */\n accountDialog?: boolean\n children: React.ReactNode\n}\n\n// Wraps the app in thirdweb, Lens and (optionally) Convex providers wired to one session.\nexport function LensAuthProvider({ auth, convex, onSignIn, accountDialog = true, children }: LensAuthProviderProps) {\n const [useConvexAuthHook] = React.useState(() => createUseConvexAuth(auth))\n const content = (\n <LensAuthState auth={auth} onSignIn={onSignIn} withConvex={!!convex}>\n {children}\n {accountDialog && <AccountDialog />}\n </LensAuthState>\n )\n return (\n <ThirdwebProvider>\n <LensProvider client={auth.lensClient}>\n {convex ? (\n <ConvexProviderWithAuth client={convex} useAuth={useConvexAuthHook}>\n {content}\n </ConvexProviderWithAuth>\n ) : content}\n </LensProvider>\n </ThirdwebProvider>\n )\n}\n\nfunction readSelectedAccount(auth: LensAuth, address: string): string | null {\n try {\n const stored = JSON.parse(localStorage.getItem(`${auth.storagePrefix}account`) ?? \"null\")\n return stored?.address === address && typeof stored.username === \"string\" ? stored.username : null\n } catch {\n return null\n }\n}\n\nfunction writeSelectedAccount(auth: LensAuth, account: SignedInAccount | null) {\n try {\n const key = `${auth.storagePrefix}account`\n if (account) localStorage.setItem(key, JSON.stringify(account))\n else localStorage.removeItem(key)\n } catch {}\n}\n\nfunction LensAuthState({ auth, onSignIn, withConvex, children }: {\n auth: LensAuth\n onSignIn?: LensAuthProviderProps[\"onSignIn\"]\n withConvex: boolean\n children: React.ReactNode\n}) {\n const wallet = useActiveAccount()\n const activeWallet = useActiveWallet()\n const { disconnect } = useDisconnect()\n const sessionKey = useSessionKey(auth)\n const [manualOpen, setManualOpen] = React.useState(false)\n const [pendingSignIn, setPendingSignIn] = React.useState<SignedInAccount | null>(null)\n\n const account = React.useMemo<SignedInAccount | null>(() => {\n if (!sessionKey) return null\n const address = sessionKey.slice(sessionKey.lastIndexOf(\":\") + 1)\n return { address, username: readSelectedAccount(auth, address) }\n }, [auth, sessionKey])\n\n const status: LensAuthStatus =\n sessionKey === undefined ? \"loading\"\n : sessionKey ? \"signed-in\"\n : wallet ? \"choosing-account\"\n : \"signed-out\"\n\n useBackgroundRefresh(auth)\n\n // A connected wallet checks the stored session is still valid (refreshing it or clearing it)\n React.useEffect(() => {\n if (wallet) void auth.resumeSession().catch(() => {})\n }, [auth, wallet?.address])\n\n const signOut = React.useCallback(async () => {\n setManualOpen(false)\n writeSelectedAccount(auth, null)\n try {\n await auth.logout()\n } finally {\n if (activeWallet) disconnect(activeWallet)\n }\n }, [auth, activeWallet, disconnect])\n\n const value = React.useMemo<LensAuthContextValue>(() => ({\n auth,\n status,\n isLoading: status === \"loading\",\n isSignedIn: status === \"signed-in\",\n wallet,\n account,\n signOut,\n openAccountDialog: () => setManualOpen(true),\n }), [auth, status, wallet, account, signOut])\n\n const required = status === \"choosing-account\"\n const dialog = React.useMemo<AccountDialogState>(() => ({\n open: required || (manualOpen && !!wallet),\n required,\n setOpen: (open) => {\n if (open) setManualOpen(true)\n else if (!required) setManualOpen(false)\n },\n completeSignIn: (signedIn) => {\n writeSelectedAccount(auth, signedIn)\n setManualOpen(false)\n if (onSignIn) setPendingSignIn(signedIn)\n },\n }), [auth, required, manualOpen, wallet, onSignIn])\n\n return (\n <LensAuthContext.Provider value={value}>\n <AccountDialogContext.Provider value={dialog}>\n {children}\n {pendingSignIn && onSignIn && (\n withConvex\n ? <ConvexSignInCallback account={pendingSignIn} onSignIn={onSignIn} done={() => setPendingSignIn(null)} />\n : <SignInCallback account={pendingSignIn} onSignIn={onSignIn} done={() => setPendingSignIn(null)} />\n )}\n </AccountDialogContext.Provider>\n </LensAuthContext.Provider>\n )\n}\n\ntype SignInCallbackProps = {\n account: SignedInAccount\n onSignIn: NonNullable<LensAuthProviderProps[\"onSignIn\"]>\n done: () => void\n}\n\nfunction SignInCallback({ account, onSignIn, done }: SignInCallbackProps) {\n React.useEffect(() => {\n Promise.resolve(onSignIn(account)).catch((err) => console.error(\"lens-convex-auth: onSignIn failed\", err)).finally(done)\n }, [account])\n return null\n}\n\n// Waits until Convex accepts the new session, so onSignIn can call authenticated Convex functions\nfunction ConvexSignInCallback(props: SignInCallbackProps) {\n const { isAuthenticated, isLoading } = useConvexAuth()\n return isAuthenticated && !isLoading ? <SignInCallback {...props} /> : null\n}\n\n// Refreshes the tokens a minute before they expire, so Convex and API calls always have a fresh one\nfunction useBackgroundRefresh(auth: LensAuth) {\n React.useEffect(() => {\n let timeout: ReturnType<typeof setTimeout> | undefined\n let stopped = false\n\n // Runs again whenever tokens are stored or cleared (a sign-in, a refresh, another tab)\n const schedule = () => {\n if (timeout) clearTimeout(timeout)\n timeout = undefined\n const tokens = auth.tokens.getStoredTokens()\n if (stopped || !tokens?.expiresAt) return\n const delay = Math.max(1000, tokens.expiresAt - Date.now() - 60 * 1000)\n timeout = setTimeout(() => void auth.tokens.refreshTokens(), delay)\n }\n\n const unsubscribe = subscribeToTokens(schedule)\n ;(async () => {\n try {\n await auth.resumeSession()\n } catch {}\n schedule()\n })()\n\n return () => {\n stopped = true\n unsubscribe()\n if (timeout) clearTimeout(timeout)\n }\n }, [auth])\n}\n","import * as React from \"react\"\nimport { useAccountsAvailable } from \"@lens-protocol/react\"\nimport { evmAddress, type Account, type AccountAvailable } from \"@lens-protocol/client\"\nimport type { Account as ThirdwebAccount } from \"thirdweb/wallets\"\nimport { Loader2 } from \"lucide-react\"\nimport { CHALLENGE_MAX_AGE_MS, CHALLENGE_REFRESH_MS, opensWalletWithDeepLink, type LensAuth, type LensChallenge } from \"../core/auth\"\nimport { fetchAccountUsername } from \"../core/onboarding\"\nimport { useAccountDialogState, useLensAuth } from \"./provider\"\nimport { CreateAccountForm, type CreatedAccount } from \"./CreateAccountForm\"\nimport { useMediaQuery } from \"./dom\"\nimport { Button } from \"./ui/button\"\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from \"./ui/dialog\"\nimport { Drawer, DrawerContent, DrawerDescription, DrawerHeader, DrawerTitle } from \"./ui/drawer\"\n\n// Lists the wallet's Lens accounts to sign in with, or the form to create one. Opens by itself when a\n// wallet connects without a Lens session, and can't be dismissed until an account is signed in to (or\n// the wallet disconnects). A dialog on desktop, a drawer on mobile.\nexport function AccountDialog() {\n const { wallet, signOut } = useLensAuth()\n const { open, required, setOpen } = useAccountDialogState()\n const isDesktop = useMediaQuery(\"(min-width: 768px)\")\n const [creating, setCreating] = React.useState(false)\n\n // Show the account list again the next time the dialog opens\n React.useEffect(() => {\n if (!open) setCreating(false)\n }, [open])\n\n const handleOpenChange = (next: boolean) => {\n if (!next && required) return\n setOpen(next)\n }\n\n const body = wallet\n ? <AccountDialogBody key={wallet.address} wallet={wallet} creating={creating} setCreating={setCreating} />\n : null\n const disconnect = (\n <Button onClick={signOut} variant=\"outline\" className=\"w-full\">\n Disconnect Wallet\n </Button>\n )\n\n if (isDesktop) {\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogContent\n className=\"sm:max-w-[425px] max-h-[80vh] overflow-y-auto\"\n showCloseButton={!required}\n onEscapeKeyDown={(e) => required && e.preventDefault()}\n onPointerDownOutside={(e) => required && e.preventDefault()}\n >\n {body}\n <div className=\"mt-4\">{disconnect}</div>\n </DialogContent>\n </Dialog>\n )\n }\n\n return (\n <Drawer open={open} onOpenChange={handleOpenChange} dismissible={!required}>\n <DrawerContent className=\"max-h-[80vh] overflow-y-auto\">\n {body}\n <div className=\"p-4\">{disconnect}</div>\n </DrawerContent>\n </Drawer>\n )\n}\n\nfunction AccountDialogBody({ wallet, creating, setCreating }: {\n wallet: ThirdwebAccount\n creating: boolean\n setCreating: (creating: boolean) => void\n}) {\n const { auth } = useLensAuth()\n const { completeSignIn } = useAccountDialogState()\n const isDesktop = useMediaQuery(\"(min-width: 768px)\")\n const { data, loading: loadingAccounts } = useAccountsAvailable({ managedBy: evmAddress(wallet.address), includeOwned: true })\n const accounts = data?.items\n const usernames = useAccountUsernames(auth, accounts)\n const loading = loadingAccounts || (!!accounts && !usernames)\n const usernameOf = React.useCallback((acc: Account) => {\n const resolved = usernames?.[acc.address.toLowerCase()]\n return resolved === undefined ? acc.username?.localName ?? null : resolved\n }, [usernames])\n // Accounts without a username aren't listed, so they don't count\n const hasAccounts = !loading && !!accounts?.some((item) => usernameOf(item.account))\n // Wallets without an account go straight to creating one\n const showCreate = creating || (!loading && !hasAccounts)\n\n const signIn = async (account: SelectableAccount, challenge: LensChallenge) => {\n // The signature request goes out before the first await, so a click handler calling this keeps its\n // user gesture, which mobile wallets need to open (see signLensChallenge).\n const signature = await auth.signChallenge(challenge, wallet)\n await auth.authenticate(challenge, signature)\n completeSignIn({ address: account.address.toLowerCase(), username: usernameOf(account) })\n }\n\n const handleCreated = async (created: CreatedAccount) => {\n completeSignIn({ address: created.address.toLowerCase(), username: created.localName })\n }\n\n const title = showCreate ? \"Create Account\" : \"Select Account\"\n const description = showCreate\n ? hasAccounts ? \"Pick a username for your new Lens account.\" : \"You don’t have a Lens account yet. Create one to continue.\"\n : \"Select an account to continue.\"\n\n const Header = isDesktop ? DialogHeader : DrawerHeader\n const Title = isDesktop ? DialogTitle : DrawerTitle\n const Description = isDesktop ? DialogDescription : DrawerDescription\n\n return (\n <>\n <Header className={isDesktop ? undefined : \"text-left\"}>\n <Title>{title}</Title>\n <Description>{description}</Description>\n </Header>\n <div className={isDesktop || !showCreate ? undefined : \"px-4\"}>\n {showCreate ? (\n <CreateAccountForm\n ownerAddress={wallet.address}\n onCreated={handleCreated}\n onBack={hasAccounts ? () => setCreating(false) : undefined}\n />\n ) : (\n <AccountList auth={auth} accounts={accounts} usernameOf={usernameOf} loading={loading} ownerAddress={wallet.address} onSign={signIn} onCreate={() => setCreating(true)} />\n )}\n </div>\n </>\n )\n}\n\n// Each account's username by lowercased address (see fetchAccountUsername), or undefined while they load.\n// An account whose lookup failed is left out, so it falls back to its global Lens username.\nfunction useAccountUsernames(auth: LensAuth, accounts?: readonly AccountAvailable[]) {\n const key = accounts?.map((item) => item.account.address.toLowerCase()).join(\",\")\n const [usernames, setUsernames] = React.useState<{ key: string; byAddress: Record<string, string | null> } | null>(null)\n\n React.useEffect(() => {\n if (key === undefined) return\n let cancelled = false\n const addresses = key ? key.split(\",\") : []\n Promise.all(addresses.map((address) =>\n fetchAccountUsername(auth, address).then((username) => [[address, username] as const], () => []),\n )).then((entries) => {\n if (!cancelled) setUsernames({ key, byAddress: Object.fromEntries(entries.flat()) })\n })\n return () => {\n cancelled = true\n }\n }, [auth, key])\n\n return usernames && usernames.key === key ? usernames.byAddress : undefined\n}\n\ntype SelectableAccount = Account & { isOwner: boolean }\n\ntype SignInStep =\n | { id: string; status: \"loading\" }\n | { id: string; status: \"sign\"; challenge: LensChallenge }\n\ntype PrefetchedChallenge = { owner: string; challenge: LensChallenge; fetchedAt: number }\n\nfunction fetchChallenge(auth: LensAuth, acc: SelectableAccount, ownerAddress: string) {\n return auth.requestChallenge({\n role: acc.isOwner ? \"ACCOUNT_OWNER\" : \"ACCOUNT_MANAGER\",\n account: acc.address,\n signer: ownerAddress,\n })\n}\n\nfunction AccountList({ auth, accounts, usernameOf, loading, ownerAddress, onSign, onCreate }: {\n auth: LensAuth\n accounts?: readonly AccountAvailable[]\n usernameOf: (account: Account) => string | null\n loading: boolean\n ownerAddress: string\n onSign: (account: SelectableAccount, challenge: LensChallenge) => Promise<void>\n onCreate: () => void\n}) {\n const [step, setStep] = React.useState<SignInStep | null>(null)\n const [errorId, setErrorId] = React.useState<string | null>(null)\n const [challenges, setChallenges] = React.useState<Record<string, PrefetchedChallenge>>({})\n\n const selectable = React.useMemo(() => (accounts ?? []).map((item, index) => {\n const acc: SelectableAccount = { ...item.account, isOwner: item.__typename === \"AccountOwned\" }\n return { acc, id: `${acc.address}-${index}` }\n }), [accounts])\n\n const prefetch = React.useCallback((acc: SelectableAccount, id: string) => {\n fetchChallenge(auth, acc, ownerAddress)\n .then((challenge) => setChallenges((prev) => ({ ...prev, [id]: { owner: ownerAddress, challenge, fetchedAt: Date.now() } })))\n .catch(() => {})\n }, [auth, ownerAddress])\n\n // Accounts can share a username across namespaces: those get their shortened address too\n const sharedUsernames = React.useMemo(() => {\n const counts = new Map<string, number>()\n for (const { acc } of selectable) {\n const username = usernameOf(acc)\n if (username) counts.set(username, (counts.get(username) ?? 0) + 1)\n }\n return new Set([...counts].filter(([, count]) => count > 1).map(([username]) => username))\n }, [selectable, usernameOf])\n\n // Fetch each account's challenge ahead of time, so a tap can ask the wallet to sign right away:\n // on mobile that tap is what lets the wallet app open (see opensWalletWithDeepLink).\n React.useEffect(() => {\n const refresh = () => {\n if (document.visibilityState !== \"visible\") return\n for (const { acc, id } of selectable) {\n if (usernameOf(acc)) prefetch(acc, id)\n }\n }\n refresh()\n const interval = setInterval(refresh, CHALLENGE_REFRESH_MS)\n document.addEventListener(\"visibilitychange\", refresh)\n return () => {\n clearInterval(interval)\n document.removeEventListener(\"visibilitychange\", refresh)\n }\n }, [selectable, usernameOf, prefetch])\n\n const readyChallenge = (id: string) => {\n if (step?.id === id && step.status === \"sign\") return step.challenge\n const prefetched = challenges[id]\n if (!prefetched || prefetched.owner !== ownerAddress) return null\n return Date.now() - prefetched.fetchedAt < CHALLENGE_MAX_AGE_MS ? prefetched.challenge : null\n }\n\n const handleClick = (acc: SelectableAccount, id: string) => {\n setErrorId(null)\n const fail = () => {\n setStep(null)\n setErrorId(id)\n prefetch(acc, id)\n }\n const challenge = readyChallenge(id)\n if (challenge) {\n // Sign now, while the tap still counts as a user gesture. A challenge can only be used once.\n const signing = onSign(acc, challenge)\n setChallenges(({ [id]: _used, ...rest }) => rest)\n setStep({ id, status: \"loading\" })\n signing.then(() => setStep(null), fail)\n return\n }\n // The challenge isn't ready yet: fetch it now. Desktop wallets sign without a user gesture;\n // on mobile it takes one more tap to open the wallet.\n setStep({ id, status: \"loading\" })\n ;(async () => {\n const fetched = await fetchChallenge(auth, acc, ownerAddress)\n if (opensWalletWithDeepLink()) return setStep({ id, status: \"sign\", challenge: fetched })\n await onSign(acc, fetched)\n setStep(null)\n })().catch(fail)\n }\n\n if (loading) {\n return (\n <div className=\"p-4\">\n <p className=\"text-sm text-muted-foreground\">Loading available profiles…</p>\n </div>\n )\n }\n\n return (\n <div className=\"py-4 space-y-3\">\n <ul className=\"space-y-2 max-h-80 overflow-y-auto\">\n {selectable.map(({ acc, id }) => {\n const username = usernameOf(acc)\n if (!username) return null\n const isLoading = step?.id === id && step.status === \"loading\"\n const awaitingSignature = step?.id === id && step.status === \"sign\"\n return (\n <li key={id}>\n <button\n type=\"button\"\n className=\"w-full text-left px-3 py-2 rounded-md border hover:bg-accent/50 flex items-center justify-between cursor-pointer disabled:cursor-default\"\n onClick={() => handleClick(acc, id)}\n disabled={step?.status === \"loading\"}\n >\n <span className=\"truncate\">\n {username}\n {sharedUsernames.has(username) && (\n <span className=\"text-muted-foreground\"> · {acc.address.slice(0, 6)}…{acc.address.slice(-4)}</span>\n )}\n </span>\n {isLoading && <Loader2 className=\"size-4 animate-spin text-muted-foreground\" />}\n {awaitingSignature && <span className=\"text-sm font-medium text-primary\">Sign in</span>}\n </button>\n {awaitingSignature && (\n <p className=\"px-1 pt-1 text-xs text-muted-foreground\">Tap again to sign the message in your wallet.</p>\n )}\n {errorId === id && (\n <p className=\"px-1 pt-1 text-xs text-destructive\">Couldn’t sign in. Please try again.</p>\n )}\n </li>\n )\n })}\n </ul>\n <Button variant=\"ghost\" className=\"w-full\" onClick={onCreate} disabled={step?.status === \"loading\"}>\n Create a new account\n </Button>\n </div>\n )\n}\n","import * as React from \"react\"\nimport { useActiveAccount, useActiveWallet } from \"thirdweb/react\"\nimport type { SessionClient } from \"@lens-protocol/client\"\nimport { Check, Loader2 } from \"lucide-react\"\nimport { CHALLENGE_MAX_AGE_MS, CHALLENGE_REFRESH_MS, opensWalletWithDeepLink, signLensChallenge, type LensChallenge } from \"../core/auth\"\nimport {\n OnboardingError,\n authenticateOnboarding,\n checkUsername,\n createLensAccount,\n createOnboardingClient,\n isUsernameTaken,\n requestOnboardingChallenge,\n signInToCreatedAccount,\n uploadAccountMetadata,\n usernameFormatError,\n} from \"../core/onboarding\"\nimport { useLensAuth } from \"./provider\"\nimport { cn } from \"./utils\"\nimport { Button } from \"./ui/button\"\nimport { Input } from \"./ui/input\"\nimport { Textarea } from \"./ui/textarea\"\nimport { Avatar, AvatarFallback, AvatarImage } from \"./ui/avatar\"\nimport { Field, FieldContent, FieldDescription, FieldGroup, FieldLabel } from \"./ui/field\"\nimport { InputGroup, InputGroupAddon, InputGroupInput, InputGroupText } from \"./ui/input-group\"\n\nexport type CreatedAccount = { address: string; localName: string }\n\ntype Step =\n | { status: \"signing\" }\n // The challenge arrived after the tap: on mobile it takes one more tap to open the wallet\n | { status: \"sign\"; challenge: LensChallenge }\n | { status: \"checking\" | \"uploading\" | \"creating\" | \"signing-in\" }\n\nconst STEP_LABELS = {\n signing: \"Waiting for signature…\",\n sign: \"Sign in wallet\",\n checking: \"Checking username…\",\n uploading: \"Uploading profile…\",\n creating: \"Creating account…\",\n \"signing-in\": \"Signing in…\",\n} satisfies Record<Step[\"status\"], string>\n\ntype Availability = { localName: string; status: \"checking\" | \"available\" | \"taken\" | \"unknown\" }\n\n// Same delay as the search on the find page\nconst USERNAME_DEBOUNCE_MS = 300\nconst MAX_PICTURE_BYTES = 10 * 1024 * 1024\n\n// Render with `key={ownerAddress}`: the onboarding session belongs to the wallet that signed it.\nexport function CreateAccountForm({ ownerAddress, onCreated, onBack }: {\n ownerAddress: string\n onCreated: (account: CreatedAccount) => Promise<void>\n onBack?: () => void\n}) {\n const { auth } = useLensAuth()\n const activeAccount = useActiveAccount()\n const wallet = useActiveWallet()\n\n const [client] = React.useState(() => createOnboardingClient(auth))\n // Kept across attempts so a retry doesn't ask for another signature or create a second account\n const session = React.useRef<SessionClient | null>(null)\n const created = React.useRef<CreatedAccount | null>(null)\n const pictureInput = React.useRef<HTMLInputElement>(null)\n\n const [username, setUsername] = React.useState(\"\")\n const [debouncedUsername, setDebouncedUsername] = React.useState(\"\")\n const [name, setName] = React.useState(\"\")\n const [bio, setBio] = React.useState(\"\")\n const [picture, setPicture] = React.useState<File | null>(null)\n const [pictureUrl, setPictureUrl] = React.useState<string | null>(null)\n\n const [availability, setAvailability] = React.useState<Availability | null>(null)\n const [usernameError, setUsernameError] = React.useState<{ localName: string; message: string } | null>(null)\n const [step, setStep] = React.useState<Step | null>(null)\n const [error, setError] = React.useState<string | null>(null)\n const [prefetched, setPrefetched] = React.useState<{ challenge: LensChallenge; fetchedAt: number } | null>(null)\n\n const formatError = username ? usernameFormatError(username) : null\n const busy = step !== null && step.status !== \"sign\"\n\n // Fetch the challenge ahead of time, so the tap on \"Create account\" can ask the wallet to sign right\n // away: on mobile that tap is what lets the wallet app open (see opensWalletWithDeepLink).\n React.useEffect(() => {\n const refresh = () => {\n if (document.visibilityState !== \"visible\" || session.current) return\n requestOnboardingChallenge(auth, client, ownerAddress)\n .then((challenge) => setPrefetched({ challenge, fetchedAt: Date.now() }))\n .catch(() => {})\n }\n refresh()\n const interval = setInterval(refresh, CHALLENGE_REFRESH_MS)\n document.addEventListener(\"visibilitychange\", refresh)\n return () => {\n clearInterval(interval)\n document.removeEventListener(\"visibilitychange\", refresh)\n }\n }, [auth, client, ownerAddress])\n\n // End the onboarding session if the form is left before the account is signed in to\n React.useEffect(() => () => {\n if (!created.current) void session.current?.logout()\n }, [])\n\n React.useEffect(() => {\n if (!picture) return setPictureUrl(null)\n const url = URL.createObjectURL(picture)\n setPictureUrl(url)\n return () => URL.revokeObjectURL(url)\n }, [picture])\n\n // Only check the username once typing pauses, not on every keystroke\n React.useEffect(() => {\n const timeout = setTimeout(() => setDebouncedUsername(username), USERNAME_DEBOUNCE_MS)\n return () => clearTimeout(timeout)\n }, [username])\n\n React.useEffect(() => {\n if (!debouncedUsername || usernameFormatError(debouncedUsername)) return\n let cancelled = false\n setAvailability({ localName: debouncedUsername, status: \"checking\" })\n isUsernameTaken(auth, debouncedUsername)\n .then((taken) => !cancelled && setAvailability({ localName: debouncedUsername, status: taken ? \"taken\" : \"available\" }))\n .catch(() => !cancelled && setAvailability({ localName: debouncedUsername, status: \"unknown\" }))\n return () => {\n cancelled = true\n }\n }, [auth, debouncedUsername])\n\n const fail = (e: unknown) => {\n setStep(null)\n if ((e as Error)?.name === \"UnauthenticatedError\") session.current = null\n setError(e instanceof OnboardingError ? e.message : \"Couldn’t create your account. Please try again.\")\n }\n\n const create = async (onboarding: SessionClient) => {\n const localName = username\n if (!created.current) {\n setStep({ status: \"checking\" })\n const reason = await checkUsername(auth, onboarding, localName)\n if (reason) {\n setUsernameError({ localName, message: reason })\n setStep(null)\n return\n }\n setStep({ status: \"uploading\" })\n const metadataUri = await uploadAccountMetadata(auth, { name: name.trim(), bio: bio.trim(), picture })\n setStep({ status: \"creating\" })\n if (!wallet) throw new OnboardingError(\"Connect your wallet\")\n const account = await createLensAccount(auth, onboarding, wallet, { localName, metadataUri })\n // account.username is its global Lens username, which it has none of in the app's namespace\n created.current = { address: account.address, localName }\n }\n setStep({ status: \"signing-in\" })\n await signInToCreatedAccount(auth, onboarding, created.current.address)\n await onCreated(created.current)\n }\n\n const continueWith = (authenticating: Promise<SessionClient | null>) => {\n authenticating\n .then(async (onboarding) => {\n if (!onboarding) return\n session.current = onboarding\n await create(onboarding)\n })\n .catch(fail)\n }\n\n const readyChallenge = () => {\n if (step?.status === \"sign\") return step.challenge\n if (!prefetched || Date.now() - prefetched.fetchedAt >= CHALLENGE_MAX_AGE_MS) return null\n return prefetched.challenge\n }\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault()\n if (busy || !activeAccount) return\n if (!username) return setUsernameError({ localName: username, message: \"Choose a username\" })\n if (formatError || availability?.status === \"taken\") return\n setError(null)\n setUsernameError(null)\n\n if (session.current) {\n setStep({ status: \"checking\" })\n create(session.current).catch(fail)\n return\n }\n\n const challenge = readyChallenge()\n if (challenge) {\n // Sign now, while the tap still counts as a user gesture. A challenge can only be used once.\n const signing = signLensChallenge(challenge, activeAccount)\n setPrefetched(null)\n setStep({ status: \"signing\" })\n continueWith(signing.then((signature) => authenticateOnboarding(client, challenge, signature)))\n return\n }\n\n // The challenge isn't ready yet: fetch it now. Desktop wallets sign without a user gesture;\n // on mobile it takes one more tap to open the wallet.\n setStep({ status: \"signing\" })\n continueWith((async () => {\n const fetched = await requestOnboardingChallenge(auth, client, ownerAddress)\n if (opensWalletWithDeepLink()) {\n setStep({ status: \"sign\", challenge: fetched })\n return null\n }\n const signature = await signLensChallenge(fetched, activeAccount)\n return authenticateOnboarding(client, fetched, signature)\n })())\n }\n\n const handlePictureChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0] ?? null\n e.target.value = \"\"\n if (file && file.size > MAX_PICTURE_BYTES) return setError(\"Choose a picture under 10 MB\")\n setError(null)\n setPicture(file)\n }\n\n const usernameMessage = (() => {\n if (formatError) return { text: formatError, isError: true }\n if (usernameError?.localName === username) return { text: usernameError.message, isError: true }\n if (availability?.localName !== username) return null\n switch (availability.status) {\n case \"checking\": return { text: \"Checking availability…\", isError: false }\n case \"available\": return { text: \"Available\", isError: false }\n case \"taken\": return { text: \"This username is taken\", isError: true }\n default: return null\n }\n })()\n\n const fallbackInitial = (name.trim() || username || \"?\").charAt(0).toUpperCase()\n const usernameStatus = availability?.localName === username && !formatError ? availability.status : null\n\n return (\n <form className=\"py-4\" onSubmit={handleSubmit} noValidate>\n <FieldGroup className=\"gap-5\">\n <Field orientation=\"horizontal\">\n <Avatar className=\"size-16\">\n {pictureUrl && <AvatarImage src={pictureUrl} alt=\"\" className=\"object-cover\" />}\n <AvatarFallback className=\"text-lg font-semibold\">{fallbackInitial}</AvatarFallback>\n </Avatar>\n <FieldContent>\n <FieldLabel htmlFor=\"create-account-picture\">\n Profile picture <span className=\"font-normal text-muted-foreground\">(optional)</span>\n </FieldLabel>\n <div className=\"flex gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => pictureInput.current?.click()} disabled={busy}>\n {picture ? \"Change\" : \"Add photo\"}\n </Button>\n {picture && (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={() => setPicture(null)} disabled={busy}>\n Remove\n </Button>\n )}\n </div>\n </FieldContent>\n <input\n ref={pictureInput}\n id=\"create-account-picture\"\n type=\"file\"\n accept=\"image/*\"\n className=\"sr-only\"\n onChange={handlePictureChange}\n disabled={busy}\n />\n </Field>\n\n <Field data-invalid={usernameMessage?.isError || undefined}>\n <FieldLabel htmlFor=\"create-account-username\">Username</FieldLabel>\n <InputGroup>\n <InputGroupAddon>\n <InputGroupText>@</InputGroupText>\n </InputGroupAddon>\n <InputGroupInput\n id=\"create-account-username\"\n value={username}\n onChange={(e) => setUsername(e.target.value.trim().toLowerCase())}\n autoComplete=\"off\"\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n spellCheck={false}\n aria-invalid={usernameMessage?.isError || undefined}\n aria-describedby=\"create-account-username-status\"\n disabled={busy}\n />\n <InputGroupAddon align=\"inline-end\">\n {usernameStatus === \"checking\" && <Loader2 className=\"animate-spin\" />}\n {usernameStatus === \"available\" && <Check />}\n </InputGroupAddon>\n </InputGroup>\n {/* Always rendered with a fixed height, so the form doesn't shift as the feedback changes */}\n <FieldDescription\n id=\"create-account-username-status\"\n aria-live=\"polite\"\n className={cn(\"min-h-5 leading-5\", usernameMessage?.isError && \"text-destructive\")}\n >\n {usernameMessage?.text}\n </FieldDescription>\n </Field>\n\n <Field>\n <FieldLabel htmlFor=\"create-account-name\">\n Name <span className=\"font-normal text-muted-foreground\">(optional)</span>\n </FieldLabel>\n <Input id=\"create-account-name\" value={name} onChange={(e) => setName(e.target.value)} maxLength={100} disabled={busy} />\n </Field>\n\n <Field>\n <FieldLabel htmlFor=\"create-account-bio\">\n Bio <span className=\"font-normal text-muted-foreground\">(optional)</span>\n </FieldLabel>\n <Textarea\n id=\"create-account-bio\"\n value={bio}\n onChange={(e) => setBio(e.target.value)}\n maxLength={300}\n rows={3}\n className=\"resize-none\"\n disabled={busy}\n />\n </Field>\n\n <Field className=\"gap-2\">\n <Button type=\"submit\" className=\"w-full\" disabled={busy || !activeAccount}>\n {busy && <Loader2 className=\"animate-spin\" />}\n {step ? STEP_LABELS[step.status] : \"Create account\"}\n </Button>\n <FieldDescription aria-live=\"polite\" className={cn(\"min-h-5 leading-5\", error && \"text-destructive\")}>\n {error ?? (step?.status === \"sign\" ? \"Tap again to sign in your wallet.\" : \"You’ll sign a message in your wallet. It’s free.\")}\n </FieldDescription>\n {onBack && (\n <Button type=\"button\" variant=\"ghost\" className=\"w-full\" onClick={onBack} disabled={busy}>\n Back to your accounts\n </Button>\n )}\n </Field>\n </FieldGroup>\n </form>\n )\n}\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../utils\"\n\nconst buttonVariants = cva(\n \"cursor-pointer inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n xl: \"h-[50px] rounded-md px-8 has-[>svg]:px-6\",\n icon: \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","import * as React from \"react\"\n\nimport { cn } from \"../utils\"\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n \"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n \"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n \"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Input }\n","import * as React from \"react\"\nimport { cn } from \"../utils\"\n\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n \"flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:ring-destructive/40\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Textarea }\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as AvatarPrimitive from \"@radix-ui/react-avatar\"\n\nimport { cn } from \"../utils\"\n\nfunction Avatar({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Root>) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n className={cn(\n \"relative flex size-8 shrink-0 overflow-hidden rounded-full\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarImage({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\"aspect-square size-full\", className)}\n {...props}\n />\n )\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"bg-muted flex size-full items-center justify-center rounded-full\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Avatar, AvatarImage, AvatarFallback }\n","\"use client\"\n\nimport { useMemo } from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"../utils\"\n\nimport { Label } from \"./label\"\nimport { Separator } from \"./separator\"\n\nfunction FieldSet({ className, ...props }: React.ComponentProps<\"fieldset\">) {\n return (\n <fieldset\n data-slot=\"field-set\"\n className={cn(\n \"flex flex-col gap-6\",\n \"has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldLegend({\n className,\n variant = \"legend\",\n ...props\n}: React.ComponentProps<\"legend\"> & { variant?: \"legend\" | \"label\" }) {\n return (\n <legend\n data-slot=\"field-legend\"\n data-variant={variant}\n className={cn(\n \"mb-3 font-medium\",\n \"data-[variant=legend]:text-base\",\n \"data-[variant=label]:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-group\"\n className={cn(\n \"group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nconst fieldVariants = cva(\n \"group/field flex w-full gap-3 data-[invalid=true]:text-destructive\",\n {\n variants: {\n orientation: {\n vertical: [\"flex-col [&>*]:w-full [&>.sr-only]:w-auto\"],\n horizontal: [\n \"flex-row items-center\",\n \"[&>[data-slot=field-label]]:flex-auto\",\n \"has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px\",\n ],\n responsive: [\n \"flex-col @md/field-group:flex-row @md/field-group:items-center [&>*]:w-full @md/field-group:[&>*]:w-auto [&>.sr-only]:w-auto\",\n \"@md/field-group:[&>[data-slot=field-label]]:flex-auto\",\n \"@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px\",\n ],\n },\n },\n defaultVariants: {\n orientation: \"vertical\",\n },\n }\n)\n\nfunction Field({\n className,\n orientation = \"vertical\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof fieldVariants>) {\n return (\n <div\n role=\"group\"\n data-slot=\"field\"\n data-orientation={orientation}\n className={cn(fieldVariants({ orientation }), className)}\n {...props}\n />\n )\n}\n\nfunction FieldContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-content\"\n className={cn(\n \"group/field-content flex flex-1 flex-col gap-1.5 leading-snug\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldLabel({\n className,\n ...props\n}: React.ComponentProps<typeof Label>) {\n return (\n <Label\n data-slot=\"field-label\"\n className={cn(\n \"group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50\",\n \"has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-4\",\n \"has-data-[state=checked]:border-primary has-data-[state=checked]:bg-primary/5 dark:has-data-[state=checked]:bg-primary/10\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"field-label\"\n className={cn(\n \"flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n <p\n data-slot=\"field-description\"\n className={cn(\n \"text-sm leading-normal font-normal text-muted-foreground group-has-[[data-orientation=horizontal]]/field:text-balance\",\n \"last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5\",\n \"[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction FieldSeparator({\n children,\n className,\n ...props\n}: React.ComponentProps<\"div\"> & {\n children?: React.ReactNode\n}) {\n return (\n <div\n data-slot=\"field-separator\"\n data-content={!!children}\n className={cn(\n \"relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2\",\n className\n )}\n {...props}\n >\n <Separator className=\"absolute inset-0 top-1/2\" />\n {children && (\n <span\n className=\"relative mx-auto block w-fit bg-background px-2 text-muted-foreground\"\n data-slot=\"field-separator-content\"\n >\n {children}\n </span>\n )}\n </div>\n )\n}\n\nfunction FieldError({\n className,\n children,\n errors,\n ...props\n}: React.ComponentProps<\"div\"> & {\n errors?: Array<{ message?: string } | undefined>\n}) {\n const content = useMemo(() => {\n if (children) {\n return children\n }\n\n if (!errors?.length) {\n return null\n }\n\n const uniqueErrors = [\n ...new Map(errors.map((error) => [error?.message, error])).values(),\n ]\n\n if (uniqueErrors?.length == 1) {\n return uniqueErrors[0]?.message\n }\n\n return (\n <ul className=\"ml-4 flex list-disc flex-col gap-1\">\n {uniqueErrors.map(\n (error, index) =>\n error?.message && <li key={index}>{error.message}</li>\n )}\n </ul>\n )\n }, [children, errors])\n\n if (!content) {\n return null\n }\n\n return (\n <div\n role=\"alert\"\n data-slot=\"field-error\"\n className={cn(\"text-sm font-normal text-destructive\", className)}\n {...props}\n >\n {content}\n </div>\n )\n}\n\nexport {\n Field,\n FieldLabel,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLegend,\n FieldSeparator,\n FieldSet,\n FieldContent,\n FieldTitle,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"../utils\"\nimport * as LabelPrimitive from \"@radix-ui/react-label\"\n\nfunction Label({\n className,\n ...props\n}: React.ComponentProps<typeof LabelPrimitive.Root>) {\n return (\n <LabelPrimitive.Root\n data-slot=\"label\"\n className={cn(\n \"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Label }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"../utils\"\n\nimport { Button } from \"./button\"\nimport { Input } from \"./input\"\nimport { Textarea } from \"./textarea\"\n\nfunction InputGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"input-group\"\n role=\"group\"\n className={cn(\n \"group/input-group relative flex w-full items-center rounded-md border border-input shadow-xs transition-[color,box-shadow] outline-none dark:bg-input/30\",\n \"h-9 min-w-0 has-[>textarea]:h-auto\",\n\n // Variants based on alignment.\n \"has-[>[data-align=inline-start]]:[&>input]:pl-2\",\n \"has-[>[data-align=inline-end]]:[&>input]:pr-2\",\n \"has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3\",\n \"has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3\",\n\n // Focus state.\n \"has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-[3px] has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50\",\n\n // Error state.\n \"has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-destructive/20 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40\",\n\n className\n )}\n {...props}\n />\n )\n}\n\nconst inputGroupAddonVariants = cva(\n \"flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n align: {\n \"inline-start\":\n \"order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]\",\n \"inline-end\":\n \"order-last pr-3 has-[>button]:mr-[-0.45rem] has-[>kbd]:mr-[-0.35rem]\",\n \"block-start\":\n \"order-first w-full justify-start px-3 pt-3 group-has-[>input]/input-group:pt-2.5 [.border-b]:pb-3\",\n \"block-end\":\n \"order-last w-full justify-start px-3 pb-3 group-has-[>input]/input-group:pb-2.5 [.border-t]:pt-3\",\n },\n },\n defaultVariants: {\n align: \"inline-start\",\n },\n }\n)\n\nfunction InputGroupAddon({\n className,\n align = \"inline-start\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof inputGroupAddonVariants>) {\n return (\n <div\n role=\"group\"\n data-slot=\"input-group-addon\"\n data-align={align}\n className={cn(inputGroupAddonVariants({ align }), className)}\n onClick={(e) => {\n if ((e.target as HTMLElement).closest(\"button\")) {\n return\n }\n e.currentTarget.parentElement?.querySelector(\"input\")?.focus()\n }}\n {...props}\n />\n )\n}\n\nconst inputGroupButtonVariants = cva(\n \"flex items-center gap-2 text-sm shadow-none\",\n {\n variants: {\n size: {\n xs: \"h-6 gap-1 rounded-[calc(var(--radius)-5px)] px-2 has-[>svg]:px-2 [&>svg:not([class*='size-'])]:size-3.5\",\n sm: \"h-8 gap-1.5 rounded-md px-2.5 has-[>svg]:px-2.5\",\n \"icon-xs\":\n \"size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0\",\n \"icon-sm\": \"size-8 p-0 has-[>svg]:p-0\",\n },\n },\n defaultVariants: {\n size: \"xs\",\n },\n }\n)\n\nfunction InputGroupButton({\n className,\n type = \"button\",\n variant = \"ghost\",\n size = \"xs\",\n ...props\n}: Omit<React.ComponentProps<typeof Button>, \"size\"> &\n VariantProps<typeof inputGroupButtonVariants>) {\n return (\n <Button\n type={type}\n data-size={size}\n variant={variant}\n className={cn(inputGroupButtonVariants({ size }), className)}\n {...props}\n />\n )\n}\n\nfunction InputGroupText({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n className={cn(\n \"flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction InputGroupInput({\n className,\n ...props\n}: React.ComponentProps<\"input\">) {\n return (\n <Input\n data-slot=\"input-group-control\"\n className={cn(\n \"flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction InputGroupTextarea({\n className,\n ...props\n}: React.ComponentProps<\"textarea\">) {\n return (\n <Textarea\n data-slot=\"input-group-control\"\n className={cn(\n \"flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n InputGroup,\n InputGroupAddon,\n InputGroupButton,\n InputGroupText,\n InputGroupInput,\n InputGroupTextarea,\n}\n","import * as React from \"react\"\n\nexport function useMediaQuery(query: string): boolean {\n return React.useSyncExternalStore(\n (onChange) => {\n const media = window.matchMedia(query)\n media.addEventListener(\"change\", onChange)\n return () => media.removeEventListener(\"change\", onChange)\n },\n () => window.matchMedia(query).matches,\n () => false,\n )\n}\n\n// The page's theme: a `dark` or `light` class on <html> (as next-themes and shadcn set it), otherwise\n// the system preference.\nfunction readTheme(): \"light\" | \"dark\" {\n const classes = document.documentElement.classList\n if (classes.contains(\"dark\")) return \"dark\"\n if (classes.contains(\"light\")) return \"light\"\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\"\n}\n\nexport function useDocumentTheme(): \"light\" | \"dark\" {\n return React.useSyncExternalStore(\n (onChange) => {\n const observer = new MutationObserver(onChange)\n observer.observe(document.documentElement, { attributes: true, attributeFilter: [\"class\"] })\n const media = window.matchMedia(\"(prefers-color-scheme: dark)\")\n media.addEventListener(\"change\", onChange)\n return () => {\n observer.disconnect()\n media.removeEventListener(\"change\", onChange)\n }\n },\n readTheme,\n () => \"light\",\n )\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\"\nimport { XIcon } from \"lucide-react\"\n\nimport { cn } from \"../utils\"\n\nfunction Dialog({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />\n}\n\nfunction DialogTrigger({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />\n}\n\nfunction DialogPortal({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />\n}\n\nfunction DialogClose({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content> & {\n showCloseButton?: boolean\n}) {\n return (\n <DialogPortal data-slot=\"dialog-portal\">\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n \"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\"\n >\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-lg leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"../utils\"\n\nfunction Drawer({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Root>) {\n return <DrawerPrimitive.Root data-slot=\"drawer\" {...props} />\n}\n\nfunction DrawerTrigger({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {\n return <DrawerPrimitive.Trigger data-slot=\"drawer-trigger\" {...props} />\n}\n\nfunction DrawerPortal({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Portal>) {\n return <DrawerPrimitive.Portal data-slot=\"drawer-portal\" {...props} />\n}\n\nfunction DrawerClose({\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Close>) {\n return <DrawerPrimitive.Close data-slot=\"drawer-close\" {...props} />\n}\n\nfunction DrawerOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {\n return (\n <DrawerPrimitive.Overlay\n data-slot=\"drawer-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DrawerContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Content>) {\n return (\n <DrawerPortal data-slot=\"drawer-portal\">\n <DrawerOverlay />\n <DrawerPrimitive.Content\n data-slot=\"drawer-content\"\n className={cn(\n \"group/drawer-content bg-background fixed z-50 flex h-auto flex-col\",\n \"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b\",\n \"data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t\",\n \"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm\",\n \"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm\",\n className\n )}\n {...props}\n >\n <div className=\"bg-muted mx-auto mt-4 hidden h-2 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block\" />\n {children}\n </DrawerPrimitive.Content>\n </DrawerPortal>\n )\n}\n\nfunction DrawerHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"drawer-header\"\n className={cn(\n \"flex flex-col gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-1.5 md:text-left\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DrawerFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"drawer-footer\"\n className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Title>) {\n return (\n <DrawerPrimitive.Title\n data-slot=\"drawer-title\"\n className={cn(\"text-foreground font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction DrawerDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Description>) {\n return (\n <DrawerPrimitive.Description\n data-slot=\"drawer-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Drawer,\n DrawerPortal,\n DrawerOverlay,\n DrawerTrigger,\n DrawerClose,\n DrawerContent,\n DrawerHeader,\n DrawerFooter,\n DrawerTitle,\n DrawerDescription,\n}\n","import * as React from \"react\"\nimport type { ConnectButtonProps } from \"thirdweb/react\"\nimport { useLensAuth } from \"./provider\"\nimport { useDocumentTheme } from \"./dom\"\nimport { Button } from \"./ui/button\"\nimport { cn } from \"./utils\"\n\n// thirdweb's ConnectButton pulls in ~480KB (gzipped) of wallet SDKs (WalletConnect, Coinbase, ...).\n// Loading it on demand keeps that out of every page's initial bundle, so pages hydrate without\n// waiting for it.\nconst ConnectButton = React.lazy(() => import(\"thirdweb/react\").then((m) => ({ default: m.ConnectButton })))\n\nexport type SignInButtonProps = {\n /** Defaults to \"Sign in\" */\n label?: React.ReactNode\n /** Defaults to \"Logout\" */\n signOutLabel?: React.ReactNode\n /** thirdweb modal theme. Defaults to the page's theme (a `dark` class on <html>, or the system's). */\n theme?: \"light\" | \"dark\"\n /** Classes for the placeholder and sign-out buttons. Size the button's wrapper to size them all alike. */\n className?: string\n /** Extra props for thirdweb's ConnectButton (wallets, connectModal, ...) */\n connectButtonProps?: Partial<Omit<ConnectButtonProps, \"client\" | \"chain\" | \"theme\">>\n}\n\n// Connects a wallet (the account dialog then opens to pick or create a Lens account) and signs out.\nexport function SignInButton({ label = \"Sign in\", signOutLabel = \"Logout\", theme, className, connectButtonProps }: SignInButtonProps) {\n const { auth, wallet, status, signOut } = useLensAuth()\n const documentTheme = useDocumentTheme()\n const [mounted, setMounted] = React.useState(false)\n React.useEffect(() => setMounted(true), [])\n\n // Same size as the real button, so nothing shifts when it loads\n const placeholder = (\n <Button variant=\"outline\" size=\"xl\" className={cn(\"min-w-[165px] px-0\", className)} disabled>\n Loading...\n </Button>\n )\n\n // thirdweb's ConnectButton doesn't render the same on the server and the client\n if (!mounted) return placeholder\n\n if (!wallet) {\n return (\n <React.Suspense fallback={placeholder}>\n <ConnectButton\n client={auth.thirdwebClient}\n chain={auth.chain}\n theme={theme ?? documentTheme}\n {...connectButtonProps}\n connectButton={{\n label,\n ...connectButtonProps?.connectButton,\n style: { height: \"50px\", minWidth: \"165px\", ...connectButtonProps?.connectButton?.style },\n }}\n />\n </React.Suspense>\n )\n }\n\n if (status !== \"signed-in\") return placeholder\n\n return (\n <Button variant=\"ghost\" size=\"xl\" className={cn(\"min-w-[165px] px-0\", className)} onClick={signOut}>\n {signOutLabel}\n </Button>\n )\n}\n"],"mappings":"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","names":["React","useActiveAccount","useActiveWallet","React","Loader2","jsx","jsx","jsx","cva","jsx","jsx","jsx","cva","jsx","cva","jsx","cva","jsx","jsx","jsxs","React","jsx","jsxs","jsx","jsx","jsxs","jsx","jsx","jsxs","jsx","jsx","jsxs","jsx","jsx","jsxs","Title","Description","Loader2","jsx","jsxs","useActiveAccount","useActiveWallet","React","jsx"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lens-convex-auth",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Drop-in sign-in for Lens apps: thirdweb wallet, Lens account sign-in and creation, and Convex auth.",
5
5
  "license": "MIT",
6
6
  "author": "Jean Ayala <hola@jeanayala.xyz>",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/constants.ts","../src/core/jwt.ts","../src/core/storage.ts","../src/core/tokens.ts","../src/core/wallet.ts","../src/core/auth.ts","../src/core/onboarding.ts"],"sourcesContent":["// Dependency-free values shared by every entry point, including the server and Convex ones.\n\nexport type LensEnvironmentName = \"mainnet\" | \"testnet\"\n\nconst LENS_API_ORIGINS: Record<LensEnvironmentName, string> = {\n mainnet: \"https://api.lens.xyz\",\n testnet: \"https://api.testnet.lens.xyz\",\n}\n\n// Lens signs its tokens as the API origin, and publishes its keys under it.\nexport function lensApiOrigin(environment: LensEnvironmentName = \"mainnet\"): string {\n return LENS_API_ORIGINS[environment]\n}\n\nexport const LENS_CHAIN_IDS: Record<LensEnvironmentName, number> = {\n mainnet: 232,\n testnet: 37111,\n}\n\n// Lens access and ID tokens are valid for 10 minutes.\nexport const LENS_TOKEN_LIFETIME_MS = 10 * 60 * 1000\n\nexport const ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/\n\n// The token the server issues for Convex (server/, convex/, cli/). Both sides must agree on these.\nexport const DEFAULT_CONVEX_TOKEN_ISSUER = \"https://lens-convex-auth.local\"\nexport const DEFAULT_CONVEX_TOKEN_AUDIENCE = \"convex\"\nexport const DEFAULT_CONVEX_TOKEN_KEY_ID = \"convex-auth-1\"\nexport const DEFAULT_CONVEX_TOKEN_ENDPOINT = \"/api/convex-token\"\n","// Claims of a JWT, without verifying it (the server verifies). Null if it isn't a JWT.\nexport function decodeJwtPayload(token: string): Record<string, unknown> | null {\n try {\n const payload = token.split(\".\")[1]\n if (!payload) return null\n const base64 = payload.replace(/-/g, \"+\").replace(/_/g, \"/\")\n const binary = atob(base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), \"=\"))\n const json = new TextDecoder().decode(Uint8Array.from(binary, (c) => c.charCodeAt(0)))\n const claims = JSON.parse(json)\n return claims && typeof claims === \"object\" ? claims : null\n } catch {\n return null\n }\n}\n\n// When a JWT expires (ms since epoch), from its `exp` claim\nexport function jwtExpiresAt(token: string): number | null {\n const exp = Number(decodeJwtPayload(token)?.exp)\n return Number.isFinite(exp) && exp > 0 ? exp * 1000 : null\n}\n\n// The Lens account a Lens ID token acts for (`act.sub`), lowercased, and the session it belongs to.\n// Null for tokens without an account (onboarding users) or that aren't JWTs.\nexport function lensSessionFromIdToken(idToken: string): { account: string; sessionId: string } | null {\n const claims = decodeJwtPayload(idToken)\n const act = claims?.act as { sub?: unknown } | null | undefined\n if (typeof act?.sub !== \"string\") return null\n return { account: act.sub.toLowerCase(), sessionId: String(claims?.sid ?? \"\") }\n}\n","import type { IStorageProvider } from \"@lens-protocol/client\"\nimport type { TokenService } from \"./tokens\"\n\n// Storage for the Lens SDK that keeps its credentials in the TokenService, so the SDK and the app\n// share one copy of the session. Everything else the SDK stores goes to localStorage under a prefix.\nexport class LensTokenStorage implements IStorageProvider {\n constructor(private tokens: TokenService, private prefix: string) {}\n\n private isCredentials(key: string) {\n return key.includes(\"credentials\") || key.includes(\"session\")\n }\n\n // The SDK only accepts a stored credentials item whose metadata is exactly\n // { version, createdAt, updatedAt }, so keep the metadata it wrote and hand it back unchanged.\n private metadataKey(key: string) {\n return `${this.prefix}${key}:metadata`\n }\n\n private credentialsMetadata(key: string) {\n const stored = localStorage.getItem(this.metadataKey(key))\n if (stored) return JSON.parse(stored)\n // Tokens stored before the metadata was kept: 3 is the SDK's current credentials schema version.\n const now = Date.now()\n return { version: 3, createdAt: now, updatedAt: now }\n }\n\n getItem(key: string): string | null {\n if (typeof window === \"undefined\") return null\n try {\n if (!this.isCredentials(key)) return localStorage.getItem(this.prefix + key)\n const tokens = this.tokens.getStoredTokens()\n if (!tokens) return null\n return JSON.stringify({\n data: { accessToken: tokens.accessToken, idToken: tokens.idToken, refreshToken: tokens.refreshToken },\n metadata: this.credentialsMetadata(key),\n })\n } catch {\n return null\n }\n }\n\n setItem(key: string, value: string): void {\n if (typeof window === \"undefined\") return\n try {\n if (!this.isCredentials(key)) return localStorage.setItem(this.prefix + key, value)\n const parsed = JSON.parse(value)\n const data = typeof parsed.data === \"string\" ? JSON.parse(parsed.data) : parsed.data\n if (data?.accessToken && data?.idToken && data?.refreshToken) {\n this.tokens.storeCredentials(data)\n localStorage.setItem(this.metadataKey(key), JSON.stringify(parsed.metadata))\n }\n } catch {}\n }\n\n removeItem(key: string): void {\n if (typeof window === \"undefined\") return\n try {\n if (!this.isCredentials(key)) return localStorage.removeItem(this.prefix + key)\n this.tokens.clearTokens()\n localStorage.removeItem(this.metadataKey(key))\n } catch {}\n }\n}\n","import { LENS_TOKEN_LIFETIME_MS } from \"./constants\"\nimport { jwtExpiresAt } from \"./jwt\"\n\nexport interface TokenData {\n accessToken: string\n idToken: string\n refreshToken: string\n expiresAt: number // when the access token expires (ms since epoch)\n}\n\nexport type LensCredentials = Pick<TokenData, \"accessToken\" | \"idToken\" | \"refreshToken\">\n\n// Dispatched on window whenever tokens are stored or cleared in this tab\nexport const TOKENS_CHANGED_EVENT = \"lens-convex-auth:tokens-changed\"\n\n// Refresh a minute before expiry for smoother UX\nconst REFRESH_BUFFER_MS = 60 * 1000\n\nconst REFRESH_MUTATION = `\n mutation Refresh($request: RefreshRequest!) {\n refresh(request: $request) {\n ... on AuthenticationTokens {\n accessToken\n idToken\n refreshToken\n }\n ... on ForbiddenError {\n reason\n }\n }\n }\n`\n\nfunction notifyTokensChanged() {\n try {\n window.dispatchEvent(new Event(TOKENS_CHANGED_EVENT))\n } catch {}\n}\n\n// Keeps the Lens session's tokens in localStorage, the single place every part of the app (the Lens\n// SDK, Convex, API calls) reads them from, and refreshes them.\nexport class TokenService {\n readonly storageKeys: { accessToken: string; idToken: string; refreshToken: string; expiresAt: string }\n private refreshPromise: Promise<TokenData | null> | null = null\n\n constructor(private options: { storagePrefix: string; graphqlUrl: string }) {\n const p = options.storagePrefix\n this.storageKeys = {\n accessToken: `${p}access_token`,\n idToken: `${p}id_token`,\n refreshToken: `${p}refresh_token`,\n expiresAt: `${p}token_expires_at`,\n }\n }\n\n storeTokens(tokens: TokenData): void {\n if (typeof window === \"undefined\") return\n try {\n localStorage.setItem(this.storageKeys.accessToken, tokens.accessToken)\n localStorage.setItem(this.storageKeys.idToken, tokens.idToken)\n localStorage.setItem(this.storageKeys.refreshToken, tokens.refreshToken)\n localStorage.setItem(this.storageKeys.expiresAt, tokens.expiresAt.toString())\n } catch {}\n notifyTokensChanged()\n }\n\n storeCredentials(credentials: LensCredentials): void {\n this.storeTokens({ ...credentials, expiresAt: Date.now() + LENS_TOKEN_LIFETIME_MS })\n }\n\n getStoredTokens(): TokenData | null {\n if (typeof window === \"undefined\") return null\n try {\n const accessToken = localStorage.getItem(this.storageKeys.accessToken)\n const idToken = localStorage.getItem(this.storageKeys.idToken)\n const refreshToken = localStorage.getItem(this.storageKeys.refreshToken)\n const storedExpiresAt = localStorage.getItem(this.storageKeys.expiresAt)\n if (!accessToken || !idToken || !refreshToken) return null\n // The access token's own expiry. The stored value is only an estimate (store time + 10 min),\n // which marks tokens read back from an old session as fresh long after they expired.\n const expiresAt = jwtExpiresAt(accessToken) ?? (storedExpiresAt ? parseInt(storedExpiresAt, 10) : 0)\n return { accessToken, idToken, refreshToken, expiresAt }\n } catch {\n return null\n }\n }\n\n clearTokens(): void {\n if (typeof window === \"undefined\") return\n try {\n for (const key of Object.values(this.storageKeys)) localStorage.removeItem(key)\n } catch {}\n notifyTokensChanged()\n }\n\n // Current access token, refreshed first if it's about to expire\n async getValidAccessToken(): Promise<string | null> {\n const tokens = this.getStoredTokens()\n if (!tokens) return null\n if (tokens.expiresAt > Date.now() + REFRESH_BUFFER_MS) return tokens.accessToken\n return (await this.refreshTokens())?.accessToken ?? null\n }\n\n // ID token for authenticating to your backend (Convex, API routes), refreshed when it's about to\n // expire (by the token's own `exp` claim). `forceRefresh` is for when the backend rejected it.\n async getFreshIdToken(forceRefresh = false): Promise<string | null> {\n const tokens = this.getStoredTokens()\n if (!tokens) return null\n const expiresAt = jwtExpiresAt(tokens.idToken) ?? 0\n const fresh = expiresAt > Date.now() + REFRESH_BUFFER_MS\n // A forced refresh right after another tab or the background refresher got new tokens reuses them\n const justIssued = expiresAt > Date.now() + 2 * REFRESH_BUFFER_MS\n if (fresh && (!forceRefresh || justIssued)) return tokens.idToken\n return (await this.refreshTokens())?.idToken ?? null\n }\n\n async isAuthenticated(): Promise<boolean> {\n return !!(await this.getValidAccessToken())\n }\n\n // Concurrent calls share one request. Clears the tokens when the session can't be refreshed.\n refreshTokens(): Promise<TokenData | null> {\n this.refreshPromise ??= this.performRefresh().finally(() => {\n this.refreshPromise = null\n })\n return this.refreshPromise\n }\n\n private async performRefresh(): Promise<TokenData | null> {\n const refreshToken = this.getStoredTokens()?.refreshToken\n if (!refreshToken) {\n this.clearTokens()\n return null\n }\n try {\n // Resuming the Lens session only reads these same tokens back, so ask the API for new ones.\n // (Each Lens SDK session keeps its own copy of the tokens and refreshes that copy itself.)\n const response = await fetch(this.options.graphqlUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ query: REFRESH_MUTATION, variables: { request: { refreshToken } } }),\n })\n const data = await response.json()\n const result = data?.data?.refresh\n if (data.errors || !result || result.reason) throw new Error(result?.reason ?? \"Refresh failed\")\n const tokens: TokenData = {\n accessToken: result.accessToken,\n idToken: result.idToken,\n refreshToken: result.refreshToken,\n expiresAt: Date.now() + LENS_TOKEN_LIFETIME_MS,\n }\n this.storeTokens(tokens)\n return tokens\n } catch {\n this.clearTokens()\n return null\n }\n }\n}\n","import { createWalletClient, custom, defineChain as defineViemChain, getAddress, hexToBigInt, hexToNumber, type Account as ViemAccount, type Chain as ViemChain, type Hex, type Transport, type WalletClient } from \"viem\"\nimport { lens as viemLens, lensTestnet as viemLensTestnet } from \"viem/chains\"\nimport { chainConfig } from \"viem/zksync\"\nimport { defineChain, type Chain } from \"thirdweb/chains\"\nimport { EIP1193, type Wallet } from \"thirdweb/wallets\"\nimport type { ThirdwebClient } from \"thirdweb\"\nimport { LENS_CHAIN_IDS, type LensEnvironmentName } from \"./constants\"\n\n// Lens Chain for thirdweb. Without an RPC URL thirdweb uses its own RPC for the chain.\nexport function lensThirdwebChain(environment: LensEnvironmentName, rpcUrl?: string): Chain {\n const testnet = environment === \"testnet\"\n return defineChain({\n id: LENS_CHAIN_IDS[environment],\n name: testnet ? \"Lens Chain Testnet\" : \"Lens Chain\",\n nativeCurrency: testnet\n ? { name: \"GRASS\", symbol: \"GRASS\", decimals: 18 }\n : { name: \"GHO\", symbol: \"GHO\", decimals: 18 },\n ...(rpcUrl ? { rpc: rpcUrl } : {}),\n ...(testnet ? { testnet: true as const } : {}),\n })\n}\n\n// Lens Chain with the zkSync config (same as `chains.mainnet` from @lens-chain/sdk/viem), so viem can\n// sign the sponsored EIP-712 transactions the Lens API returns. Typed as a plain `Chain` because\n// `handleOperationWith` takes a plain viem `WalletClient`.\nexport function lensViemChain(environment: LensEnvironmentName): ViemChain {\n return defineViemChain({ ...(environment === \"testnet\" ? viemLensTestnet : viemLens), ...chainConfig })\n}\n\n// A viem wallet client for the connected thirdweb wallet, as `handleOperationWith` expects:\n// hoisted account and a Lens chain. Works for every thirdweb wallet, not only injected ones.\nexport function createLensWalletClient(opts: {\n wallet: Wallet\n client: ThirdwebClient\n chain: Chain\n viemChain: ViemChain\n}): WalletClient<Transport, ViemChain, ViemAccount> {\n const account = opts.wallet.getAccount()\n if (!account) throw new Error(\"Connect your wallet\")\n const provider = EIP1193.toProvider({ wallet: opts.wallet, chain: opts.chain, client: opts.client })\n return createWalletClient({\n account: getAddress(account.address),\n chain: opts.viemChain,\n transport: custom({\n request: ({ method, params }) => {\n if (method === \"eth_sendTransaction\") {\n // viem sends hex-encoded fields (e.g. `type: \"0x2\"`) that thirdweb's local signers reject.\n // thirdweb re-estimates gas and fees for Lens Chain anyway, so pass only what it needs.\n const [tx] = params as [{ to: Hex; data?: Hex; value?: Hex; nonce?: Hex }]\n return provider.request({\n method,\n params: [{\n to: tx.to,\n data: tx.data,\n value: tx.value ? hexToBigInt(tx.value) : undefined,\n nonce: tx.nonce ? hexToNumber(tx.nonce) : undefined,\n }],\n })\n }\n return provider.request({ method, params })\n },\n }),\n })\n}\n","import { PublicClient, evmAddress, mainnet, signatureFrom, testnet, type SessionClient, type UUID } from \"@lens-protocol/client\"\nimport { createThirdwebClient, type ThirdwebClient } from \"thirdweb\"\nimport type { Chain } from \"thirdweb/chains\"\nimport type { Chain as ViemChain } from \"viem\"\nimport { ADDRESS_RE, DEFAULT_CONVEX_TOKEN_ENDPOINT, lensApiOrigin, type LensEnvironmentName } from \"./constants\"\nimport { lensSessionFromIdToken } from \"./jwt\"\nimport { LensTokenStorage } from \"./storage\"\nimport { TokenService, type LensCredentials } from \"./tokens\"\nimport { lensThirdwebChain, lensViemChain } from \"./wallet\"\n\nexport type LensAuthOptions = {\n /** thirdweb client ID (https://thirdweb.com/dashboard) */\n thirdwebClientId: string\n /** Your Lens app address (https://developer.lens.xyz/apps). Tokens are issued for this app. */\n lensAppAddress: string\n /** Defaults to \"mainnet\" */\n environment?: LensEnvironmentName\n /** Lens Chain RPC for thirdweb. Defaults to thirdweb's RPC. */\n lensChainRpcUrl?: string\n /** Prefix of the localStorage keys the session is stored under. Defaults to \"lens_\". */\n storagePrefix?: string\n /** Route that exchanges a Lens ID token for a Convex token. Defaults to \"/api/convex-token\". */\n convexTokenEndpoint?: string\n}\n\nexport type LensLoginRole = \"ACCOUNT_OWNER\" | \"ACCOUNT_MANAGER\"\n\nexport type LensChallenge = { id: UUID; text: string }\n\nexport type MessageSigner = {\n signMessage: (args: { message: string }) => Promise<string>\n}\n\n// The signed-in Lens account (lowercased address) and its session, read from the stored ID token\nexport type LensSessionInfo = { account: string; sessionId: string }\n\nexport type LensAuth = ReturnType<typeof createLensAuth>\n\n// Challenges are fetched ahead of time so a tap can sign right away: how often they're replaced, and how\n// old one can be to still be used.\nexport const CHALLENGE_REFRESH_MS = 2 * 60 * 1000\nexport const CHALLENGE_MAX_AGE_MS = 4 * 60 * 1000\n\n// On phones and tablets thirdweb opens the wallet app with a deep link to sign (same check as its\n// internal isMobile), and that deep link only works right after a tap.\nexport function opensWalletWithDeepLink() {\n if (typeof navigator === \"undefined\") return false\n const ua = navigator.userAgent\n return /iPhone|iPad|iPod|Android/i.test(ua) || (/Macintosh/.test(ua) && navigator.maxTouchPoints > 1)\n}\n\n// Asks the wallet to sign synchronously (no awaits before it), so call it directly from a click handler.\nexport function signLensChallenge(challenge: LensChallenge, signer: MessageSigner): Promise<string> {\n return signer.signMessage({ message: challenge.text })\n}\n\n// A Lens SDK session's tokens\nexport function sessionCredentials(session: SessionClient): LensCredentials {\n const credentials = session.getCredentials()\n if (credentials.isErr()) throw credentials.error\n if (!credentials.value) throw new Error(\"The Lens session has no credentials\")\n return credentials.value\n}\n\n// Create once per app (at module level) and pass to <LensAuthProvider>.\nexport function createLensAuth(options: LensAuthOptions) {\n if (!options.thirdwebClientId) throw new Error(\"lens-convex-auth: thirdwebClientId is required\")\n if (!ADDRESS_RE.test(options.lensAppAddress ?? \"\")) {\n throw new Error(\"lens-convex-auth: lensAppAddress must be your Lens app address (0x…)\")\n }\n\n const environment: LensEnvironmentName = options.environment ?? \"mainnet\"\n const storagePrefix = options.storagePrefix ?? \"lens_\"\n const appAddress = options.lensAppAddress\n const convexTokenEndpoint = options.convexTokenEndpoint ?? DEFAULT_CONVEX_TOKEN_ENDPOINT\n\n const tokens = new TokenService({ storagePrefix, graphqlUrl: `${lensApiOrigin(environment)}/graphql` })\n const thirdwebClient: ThirdwebClient = createThirdwebClient({ clientId: options.thirdwebClientId })\n const chain: Chain = lensThirdwebChain(environment, options.lensChainRpcUrl)\n const viemChain: ViemChain = lensViemChain(environment)\n const lensEnvironment = environment === \"testnet\" ? testnet : mainnet\n const lensClient = PublicClient.create({\n environment: lensEnvironment,\n storage: typeof window !== \"undefined\" ? new LensTokenStorage(tokens, `${storagePrefix}custom_`) : undefined,\n })\n\n // The signed-in account, or null when signed out\n function getSession(): LensSessionInfo | null {\n const idToken = tokens.getStoredTokens()?.idToken\n return idToken ? lensSessionFromIdToken(idToken) : null\n }\n\n // True when there's a valid session, refreshing its tokens first if needed (a session that can't be\n // refreshed is cleared). Also resumes it in the Lens client, so Lens SDK calls and hooks act as the\n // signed-in account.\n async function resumeSession(): Promise<boolean> {\n if (!(await tokens.isAuthenticated())) return false\n if (!lensClient.currentSession?.isSessionClient()) await lensClient.resumeSession()\n return true\n }\n\n // Logging in is split in two (challenge, then sign + authenticate) instead of using `lensClient.login`,\n // so the signature can be requested straight from a tap. On mobile, WalletConnect opens the wallet app\n // with a deep link when asked to sign, and iOS only allows that right after a user gesture: after the\n // challenge round trip the link is blocked and the wallet never shows the request.\n async function requestChallenge(opts: { role: LensLoginRole; account: string; signer: string }): Promise<LensChallenge> {\n const app = evmAddress(appAddress)\n const account = evmAddress(opts.account)\n const signer = evmAddress(opts.signer)\n const challenge = await lensClient.challenge(\n opts.role === \"ACCOUNT_MANAGER\"\n ? { accountManager: { account, app, manager: signer } }\n : { accountOwner: { account, app, owner: signer } },\n )\n if (challenge.isErr()) throw challenge.error\n return challenge.value\n }\n\n async function authenticate(challenge: LensChallenge, signature: string): Promise<SessionClient> {\n const authenticated = await lensClient.authenticate({ id: challenge.id, signature: signatureFrom(signature) })\n if (authenticated.isErr()) throw authenticated.error\n tokens.storeCredentials(sessionCredentials(authenticated.value))\n return authenticated.value\n }\n\n async function logout(): Promise<void> {\n tokens.clearTokens()\n // PublicClient has no logout; logout exists on SessionClient\n const session = lensClient.currentSession\n if (session && session.isSessionClient()) await session.logout()\n }\n\n // fetch() with the Lens ID token as `Authorization: Bearer`, retried once with a refreshed token on 401.\n // Verify it on the server with `getLensSession` from \"lens-convex-auth/server\".\n async function authFetch(input: RequestInfo | URL, init: RequestInit = {}): Promise<Response> {\n const send = async (forceRefresh: boolean) => {\n const idToken = await tokens.getFreshIdToken(forceRefresh)\n const headers = new Headers(init.headers)\n if (idToken) headers.set(\"Authorization\", `Bearer ${idToken}`)\n return fetch(input, { ...init, headers })\n }\n const response = await send(false)\n return response.status === 401 && getSession() ? send(true) : response\n }\n\n // Convex can't verify Lens ID tokens itself (they have no `kid` header), so the server verifies the\n // Lens ID token and issues a Convex token for the same account (see \"lens-convex-auth/server\").\n async function fetchConvexToken(forceRefresh = false): Promise<string | null> {\n const idToken = await tokens.getFreshIdToken(forceRefresh)\n if (!idToken) return null\n try {\n const res = await fetch(convexTokenEndpoint, { method: \"POST\", headers: { Authorization: `Bearer ${idToken}` } })\n if (!res.ok) return null\n const { token } = await res.json()\n return typeof token === \"string\" ? token : null\n } catch {\n return null\n }\n }\n\n return {\n environment,\n appAddress,\n storagePrefix,\n thirdwebClient,\n chain,\n viemChain,\n lensClient,\n lensEnvironment,\n tokens,\n getSession,\n resumeSession,\n requestChallenge,\n signChallenge: signLensChallenge,\n authenticate,\n logout,\n fetch: authFetch,\n fetchConvexToken,\n }\n}\n","import { PublicClient, evmAddress, signatureFrom, uri, type Account, type SessionClient } from \"@lens-protocol/client\"\nimport { canCreateUsername, createAccountWithUsername, fetchAccount, fetchUsername } from \"@lens-protocol/client/actions\"\nimport { handleOperationWith } from \"@lens-protocol/client/viem\"\nimport { account as accountMetadata } from \"@lens-protocol/metadata\"\nimport { StorageClient, immutable } from \"@lens-chain/storage-client\"\nimport { getTransactionReceipt } from \"viem/actions\"\nimport type { Wallet } from \"thirdweb/wallets\"\nimport type { LensAuth, LensChallenge } from \"./auth\"\nimport { sessionCredentials } from \"./auth\"\nimport { LENS_CHAIN_IDS } from \"./constants\"\nimport { createLensWalletClient } from \"./wallet\"\n\n// An error whose message can be shown to the user as is.\nexport class OnboardingError extends Error {\n name = \"OnboardingError\"\n}\n\n// Creating an account takes a session as an onboarding user (a wallet signed in without a Lens Account).\n// It runs on its own client, whose storage is in memory, so that session never reaches the app's token\n// storage: until the account exists and is signed in to, the app must not treat the wallet as signed in.\nexport function createOnboardingClient(auth: LensAuth) {\n return PublicClient.create({ environment: auth.lensEnvironment })\n}\n\nexport async function requestOnboardingChallenge(auth: LensAuth, client: PublicClient, walletAddress: string): Promise<LensChallenge> {\n const challenge = await client.challenge({\n onboardingUser: { app: evmAddress(auth.appAddress), wallet: evmAddress(walletAddress) },\n })\n if (challenge.isErr()) throw challenge.error\n return challenge.value\n}\n\nexport async function authenticateOnboarding(client: PublicClient, challenge: LensChallenge, signature: string): Promise<SessionClient> {\n const authenticated = await client.authenticate({ id: challenge.id, signature: signatureFrom(signature) })\n if (authenticated.isErr()) throw authenticated.error\n return authenticated.value\n}\n\n// The global Lens namespace takes lowercase letters, numbers, \"-\" and \"_\", and can't start with \"-\" or \"_\".\n// Its other rules (length, reserved names, price) are checked by the Lens API in checkUsername.\nconst USERNAME_PATTERN = /^[a-z0-9][a-z0-9_-]*$/\n\nexport function usernameFormatError(localName: string): string | null {\n if (!localName) return \"Choose a username\"\n if (/^[-_]/.test(localName)) return \"Start with a letter or a number\"\n if (!USERNAME_PATTERN.test(localName)) return \"Use only lowercase letters, numbers, - and _\"\n return null\n}\n\n// Needs no session, so it can run while the user types.\nexport async function isUsernameTaken(auth: LensAuth, localName: string): Promise<boolean> {\n const result = await fetchUsername(auth.lensClient, { username: { localName } })\n if (result.isErr()) throw result.error\n return result.value !== null\n}\n\ntype NamespaceValidationFailed = {\n reason: string\n unsatisfiedRules: { required: { message: string }[] } | null\n}\n\nfunction validationFailedMessage(failed: NamespaceValidationFailed) {\n return failed.unsatisfiedRules?.required[0]?.message || failed.reason\n}\n\n// Returns why the username can't be created, or null if it can.\nexport async function checkUsername(session: SessionClient, localName: string): Promise<string | null> {\n const result = await canCreateUsername(session, { localName })\n if (result.isErr()) throw result.error\n switch (result.value.__typename) {\n case \"NamespaceOperationValidationPassed\":\n return null\n case \"UsernameTaken\":\n return \"This username is taken\"\n case \"NamespaceOperationValidationFailed\":\n return validationFailedMessage(result.value)\n case \"NamespaceOperationValidationUnknown\":\n return \"This username can’t be created here. Try another one.\"\n }\n}\n\nlet storageClient: StorageClient | null = null\n\nexport type AccountProfile = {\n name?: string\n bio?: string\n picture?: File | null\n}\n\n// Uploads the account metadata (and its picture) to Grove, and returns the metadata URI.\nexport async function uploadAccountMetadata(auth: LensAuth, profile: AccountProfile): Promise<string> {\n storageClient ??= StorageClient.create()\n const acl = immutable(LENS_CHAIN_IDS[auth.environment])\n const picture = profile.picture ? (await storageClient.uploadFile(profile.picture, { acl })).uri : undefined\n const metadata = accountMetadata({\n name: profile.name || undefined,\n bio: profile.bio || undefined,\n picture,\n })\n const { uri: metadataUri } = await storageClient.uploadAsJson(metadata, { acl })\n return metadataUri\n}\n\n// How long to wait for a new account to be listed once its transaction is indexed\nconst ACCOUNT_POLL_ATTEMPTS = 15\nconst ACCOUNT_POLL_INTERVAL_MS = 2000\n\n// Creates an account owned by the onboarding user's wallet. Most apps sponsor it; otherwise the wallet\n// is asked to send the transaction.\nexport async function createLensAccount(\n auth: LensAuth,\n session: SessionClient,\n wallet: Wallet,\n request: { localName: string; metadataUri: string },\n): Promise<Account> {\n const created = await createAccountWithUsername(session, {\n username: { localName: request.localName },\n metadataUri: uri(request.metadataUri),\n })\n if (created.isErr()) throw created.error\n const result = created.value\n switch (result.__typename) {\n case \"UsernameTaken\":\n throw new OnboardingError(\"This username is taken\")\n case \"NamespaceOperationValidationFailed\":\n throw new OnboardingError(validationFailedMessage(result))\n case \"TransactionWillFail\":\n throw new OnboardingError(result.reason)\n }\n\n const walletClient = createLensWalletClient({ wallet, client: auth.thirdwebClient, chain: auth.chain, viemChain: auth.viemChain })\n const sent = await handleOperationWith(walletClient)(result)\n if (sent.isErr()) throw sent.error\n const hash = sent.value\n\n const indexed = await session.waitForTransaction(hash)\n if (indexed.isErr()) {\n // The Lens API stops waiting for indexing after 10s on mainnet, so the receipt decides whether\n // the transaction failed. If it can't be read either, the account lookup below still settles it.\n const receipt = await getTransactionReceipt(walletClient, { hash }).catch(() => null)\n if (receipt?.status === \"reverted\") throw indexed.error\n }\n\n for (let attempt = 0; attempt < ACCOUNT_POLL_ATTEMPTS; attempt++) {\n const fetched = await fetchAccount(session, { txHash: hash })\n if (fetched.isOk() && fetched.value) return fetched.value\n await new Promise((resolve) => setTimeout(resolve, ACCOUNT_POLL_INTERVAL_MS))\n }\n throw new OnboardingError(\"Your account was created but isn’t ready yet. Sign in to it again in a minute.\")\n}\n\n// Signs the app in to the new account without another signature: the onboarding session switches to it,\n// and its tokens are handed to the app's Lens client, like a sign-in from the account list.\nexport async function signInToCreatedAccount(auth: LensAuth, session: SessionClient, accountAddress: string): Promise<void> {\n const switched = await session.switchAccount({ account: evmAddress(accountAddress) })\n if (switched.isErr()) throw switched.error\n auth.tokens.storeCredentials(sessionCredentials(switched.value))\n const resumed = await auth.lensClient.resumeSession()\n if (resumed.isErr()) throw resumed.error\n}\n"],"mappings":"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","names":["testnet","PublicClient","evmAddress","signatureFrom","PublicClient","evmAddress","signatureFrom"]}