Skip to content

Commit 5050a01

Browse files
Merge pull request #381 from LIT-Protocol/feat/farcaster-app-setup
chore(dashboard): reduce auth to wallet-only in miniapps
2 parents 2b59f0e + aa37be1 commit 5050a01

File tree

3 files changed

+182
-113
lines changed

3 files changed

+182
-113
lines changed

packages/apps/app-dashboard/public/.well-known/farcaster.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
{
22
"accountAssociation": {
3-
"header": "eyJmaWQiOjEzNzAyOTksInR5cGUiOiJjdXN0b2R5Iiwia2V5IjoiMHhBMDdENTk2QTkzNDFEMkY2YkM0RWYxQmM4NmJCMGUxNWExMEQxYzk1In0",
3+
"header": "eyJmaWQiOjEzNzAyOTksInR5cGUiOiJhdXRoIiwia2V5IjoiMHgxNkU5RDc1Yjk3ODE2MzBkYTM5MjI1YzJlYTQyNmFENTdEQjlkMDkwIn0",
44
"payload": "eyJkb21haW4iOiJkYXNoYm9hcmQuaGV5dmluY2VudC5haSJ9",
5-
"signature": "hRgY97LoEMnZEVIoaXn8wmY8gdLHnkMUOziBNfqku/oATg8iTYr9YSAVirnFiB4wR7cOA5zc83SfVLyLpvmBshs="
5+
"signature": "d9mQieBS7e1cmiK5/zmwoe/ceWfq0yWipy90E8UCmM1571/eacZG4CmdeWrGaLr0xKI6xopPiqHb2McrgGlx2hw="
6+
},
7+
"baseBuilder": {
8+
"ownerAddress": "0x0aAE6bc9689bED885c35a38d726dd1875005708E"
69
},
710
"miniapp": {
811
"version": "1",

packages/apps/app-dashboard/src/components/user-dashboard/auth/AuthMethods.tsx

Lines changed: 148 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import { Dispatch, SetStateAction, useEffect } from 'react';
22
import { theme as themeImport, fonts } from '../connect/ui/theme';
33
import { AuthView } from '../connect/Connect';
4+
import { useFarcaster } from '@/hooks/shared/useFarcaster';
5+
import Loading from '@/components/shared/ui/Loading';
46

57
interface AuthMethodsProps {
68
setView: Dispatch<SetStateAction<AuthView>>;
79
clearError?: () => void;
810
}
911

1012
const AuthMethods = ({ setView, clearError }: AuthMethodsProps) => {
13+
const { isInFarcaster, isLoading } = useFarcaster();
14+
1115
useEffect(() => {
1216
if (clearError) {
1317
clearError();
@@ -24,155 +28,188 @@ const AuthMethods = ({ setView, clearError }: AuthMethodsProps) => {
2428
Please login in or sign up to continue.
2529
</p>
2630
</div>
27-
<div className="flex flex-col items-center space-y-3">
28-
<div
29-
className={`w-full sm:w-3/4 md:w-3/4 lg:w-full py-3 px-4 flex items-center justify-between bg-white dark:bg-gray-950 border border-gray-200 dark:border-white/10 rounded-lg hover:bg-gray-100 dark:hover:bg-white/[0.05] transition-colors cursor-pointer`}
30-
onClick={() => setView('email')}
31-
>
32-
<div className="flex items-center">
33-
<div className={`w-5 h-5 mr-3 flex items-center justify-center`}>
31+
{isLoading ? (
32+
<Loading />
33+
) : (
34+
<div className="flex flex-col items-center space-y-3">
35+
{!isInFarcaster && (
36+
<div
37+
className={`w-full sm:w-3/4 md:w-3/4 lg:w-full py-3 px-4 flex items-center justify-between bg-white dark:bg-gray-950 border border-gray-200 dark:border-white/10 rounded-lg hover:bg-gray-100 dark:hover:bg-white/[0.05] transition-colors cursor-pointer`}
38+
onClick={() => setView('email')}
39+
>
40+
<div className="flex items-center">
41+
<div className={`w-5 h-5 mr-3 flex items-center justify-center`}>
42+
<svg
43+
viewBox="0 0 24 24"
44+
fill="none"
45+
stroke={themeImport.brandOrange}
46+
className="w-4 h-4"
47+
>
48+
<path
49+
strokeLinecap="round"
50+
strokeLinejoin="round"
51+
strokeWidth={2}
52+
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
53+
/>
54+
</svg>
55+
</div>
56+
<span
57+
className={`text-sm font-medium text-gray-900 dark:text-white`}
58+
style={fonts.heading}
59+
>
60+
Email
61+
</span>
62+
</div>
3463
<svg
35-
viewBox="0 0 24 24"
64+
className={`w-4 h-4 text-gray-600 dark:text-white/60`}
3665
fill="none"
37-
stroke={themeImport.brandOrange}
38-
className="w-4 h-4"
66+
stroke="currentColor"
67+
viewBox="0 0 24 24"
3968
>
4069
<path
4170
strokeLinecap="round"
4271
strokeLinejoin="round"
4372
strokeWidth={2}
44-
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
73+
d="M9 5l7 7-7 7"
4574
/>
4675
</svg>
4776
</div>
48-
<span
49-
className={`text-sm font-medium text-gray-900 dark:text-white`}
50-
style={fonts.heading}
51-
>
52-
Email
53-
</span>
54-
</div>
55-
<svg
56-
className={`w-4 h-4 text-gray-600 dark:text-white/60`}
57-
fill="none"
58-
stroke="currentColor"
59-
viewBox="0 0 24 24"
60-
>
61-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
62-
</svg>
63-
</div>
77+
)}
6478

65-
<div
66-
className={`w-full sm:w-3/4 md:w-3/4 lg:w-full py-3 px-4 flex items-center justify-between bg-white dark:bg-gray-950 border border-gray-200 dark:border-white/10 rounded-lg hover:bg-gray-100 dark:hover:bg-white/[0.05] transition-colors cursor-pointer`}
67-
onClick={() => setView('phone')}
68-
>
69-
<div className="flex items-center">
70-
<div className={`w-5 h-5 mr-3 flex items-center justify-center`}>
79+
{!isInFarcaster && (
80+
<div
81+
className={`w-full sm:w-3/4 md:w-3/4 lg:w-full py-3 px-4 flex items-center justify-between bg-white dark:bg-gray-950 border border-gray-200 dark:border-white/10 rounded-lg hover:bg-gray-100 dark:hover:bg-white/[0.05] transition-colors cursor-pointer`}
82+
onClick={() => setView('phone')}
83+
>
84+
<div className="flex items-center">
85+
<div className={`w-5 h-5 mr-3 flex items-center justify-center`}>
86+
<svg
87+
viewBox="0 0 24 24"
88+
fill="none"
89+
stroke={themeImport.brandOrange}
90+
className="w-4 h-4"
91+
>
92+
<path
93+
strokeLinecap="round"
94+
strokeLinejoin="round"
95+
strokeWidth={2}
96+
d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z"
97+
/>
98+
</svg>
99+
</div>
100+
<span
101+
className={`text-sm font-medium text-gray-900 dark:text-white`}
102+
style={fonts.heading}
103+
>
104+
Phone
105+
</span>
106+
</div>
71107
<svg
72-
viewBox="0 0 24 24"
108+
className={`w-4 h-4 text-gray-600 dark:text-white/60`}
73109
fill="none"
74-
stroke={themeImport.brandOrange}
75-
className="w-4 h-4"
110+
stroke="currentColor"
111+
viewBox="0 0 24 24"
76112
>
77113
<path
78114
strokeLinecap="round"
79115
strokeLinejoin="round"
80116
strokeWidth={2}
81-
d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z"
117+
d="M9 5l7 7-7 7"
82118
/>
83119
</svg>
84120
</div>
85-
<span
86-
className={`text-sm font-medium text-gray-900 dark:text-white`}
87-
style={fonts.heading}
88-
>
89-
Phone
90-
</span>
91-
</div>
92-
<svg
93-
className={`w-4 h-4 text-gray-600 dark:text-white/60`}
94-
fill="none"
95-
stroke="currentColor"
96-
viewBox="0 0 24 24"
97-
>
98-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
99-
</svg>
100-
</div>
121+
)}
101122

102-
<div
103-
className={`w-full sm:w-3/4 md:w-3/4 lg:w-full py-3 px-4 flex items-center justify-between bg-white dark:bg-gray-950 border border-gray-200 dark:border-white/10 rounded-lg hover:bg-gray-100 dark:hover:bg-white/[0.05] transition-colors cursor-pointer`}
104-
onClick={() => setView('wallet')}
105-
>
106-
<div className="flex items-center">
107-
<div className={`w-5 h-5 mr-3 flex items-center justify-center`}>
108-
<svg
109-
viewBox="0 0 24 24"
110-
fill="none"
111-
stroke={themeImport.brandOrange}
112-
className="w-4 h-4"
123+
<div
124+
className={`w-full sm:w-3/4 md:w-3/4 lg:w-full py-3 px-4 flex items-center justify-between bg-white dark:bg-gray-950 border border-gray-200 dark:border-white/10 rounded-lg hover:bg-gray-100 dark:hover:bg-white/[0.05] transition-colors cursor-pointer`}
125+
onClick={() => setView('wallet')}
126+
>
127+
<div className="flex items-center">
128+
<div className={`w-5 h-5 mr-3 flex items-center justify-center`}>
129+
<svg
130+
viewBox="0 0 24 24"
131+
fill="none"
132+
stroke={themeImport.brandOrange}
133+
className="w-4 h-4"
134+
>
135+
<path
136+
strokeLinecap="round"
137+
strokeLinejoin="round"
138+
strokeWidth={2}
139+
d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"
140+
/>
141+
</svg>
142+
</div>
143+
<span
144+
className={`text-sm font-medium text-gray-900 dark:text-white`}
145+
style={fonts.heading}
113146
>
114-
<path
115-
strokeLinecap="round"
116-
strokeLinejoin="round"
117-
strokeWidth={2}
118-
d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"
119-
/>
120-
</svg>
147+
Wallet
148+
</span>
121149
</div>
122-
<span
123-
className={`text-sm font-medium text-gray-900 dark:text-white`}
124-
style={fonts.heading}
150+
<svg
151+
className={`w-4 h-4 text-gray-600 dark:text-white/60`}
152+
fill="none"
153+
stroke="currentColor"
154+
viewBox="0 0 24 24"
125155
>
126-
Wallet
127-
</span>
156+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
157+
</svg>
128158
</div>
129-
<svg
130-
className={`w-4 h-4 text-gray-600 dark:text-white/60`}
131-
fill="none"
132-
stroke="currentColor"
133-
viewBox="0 0 24 24"
134-
>
135-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
136-
</svg>
137-
</div>
138159

139-
<div
140-
className={`w-full sm:w-3/4 md:w-3/4 lg:w-full py-3 px-4 flex items-center justify-between bg-white dark:bg-gray-950 border border-gray-200 dark:border-white/10 rounded-lg hover:bg-gray-100 dark:hover:bg-white/[0.05] transition-colors cursor-pointer`}
141-
onClick={() => setView('webauthn')}
142-
>
143-
<div className="flex items-center">
144-
<div className={`w-5 h-5 mr-3 flex items-center justify-center`}>
160+
{isInFarcaster && (
161+
<div className="w-full sm:w-3/4 md:w-3/4 lg:w-full p-3 bg-orange-50 dark:bg-orange-950/20 border border-orange-200 dark:border-orange-800/30 rounded-lg">
162+
<p className="text-xs text-orange-800 dark:text-orange-200 text-center">
163+
Wallet authentication is the only method available in Mini Apps.
164+
</p>
165+
</div>
166+
)}
167+
168+
{!isInFarcaster && (
169+
<div
170+
className={`w-full sm:w-3/4 md:w-3/4 lg:w-full py-3 px-4 flex items-center justify-between bg-white dark:bg-gray-950 border border-gray-200 dark:border-white/10 rounded-lg hover:bg-gray-100 dark:hover:bg-white/[0.05] transition-colors cursor-pointer`}
171+
onClick={() => setView('webauthn')}
172+
>
173+
<div className="flex items-center">
174+
<div className={`w-5 h-5 mr-3 flex items-center justify-center`}>
175+
<svg
176+
viewBox="0 0 24 24"
177+
fill="none"
178+
stroke={themeImport.brandOrange}
179+
className="w-4 h-4"
180+
>
181+
<path
182+
strokeLinecap="round"
183+
strokeLinejoin="round"
184+
strokeWidth={2}
185+
d="M15 7a3 3 0 013 3m3 0a6 6 0 01-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1121.75 8.25z"
186+
/>
187+
</svg>
188+
</div>
189+
<span
190+
className={`text-sm font-medium text-gray-900 dark:text-white`}
191+
style={fonts.heading}
192+
>
193+
Passkey
194+
</span>
195+
</div>
145196
<svg
146-
viewBox="0 0 24 24"
197+
className={`w-4 h-4 text-gray-600 dark:text-white/60`}
147198
fill="none"
148-
stroke={themeImport.brandOrange}
149-
className="w-4 h-4"
199+
stroke="currentColor"
200+
viewBox="0 0 24 24"
150201
>
151202
<path
152203
strokeLinecap="round"
153204
strokeLinejoin="round"
154205
strokeWidth={2}
155-
d="M15 7a3 3 0 013 3m3 0a6 6 0 01-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1121.75 8.25z"
206+
d="M9 5l7 7-7 7"
156207
/>
157208
</svg>
158209
</div>
159-
<span
160-
className={`text-sm font-medium text-gray-900 dark:text-white`}
161-
style={fonts.heading}
162-
>
163-
Passkey
164-
</span>
165-
</div>
166-
<svg
167-
className={`w-4 h-4 text-gray-600 dark:text-white/60`}
168-
fill="none"
169-
stroke="currentColor"
170-
viewBox="0 0 24 24"
171-
>
172-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
173-
</svg>
210+
)}
174211
</div>
175-
</div>
212+
)}
176213
</div>
177214
);
178215
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { useState, useEffect } from 'react';
2+
import { sdk } from '@farcaster/miniapp-sdk';
3+
4+
/**
5+
* Hook to detect if the app is running inside Farcaster
6+
* @returns boolean indicating if running in Farcaster miniapp context
7+
*/
8+
export function useFarcaster() {
9+
const [isInFarcaster, setIsInFarcaster] = useState(false);
10+
const [isLoading, setIsLoading] = useState(true);
11+
12+
useEffect(() => {
13+
const checkFarcasterContext = async () => {
14+
try {
15+
const isMiniApp = await sdk.isInMiniApp();
16+
setIsInFarcaster(isMiniApp);
17+
} catch (error) {
18+
// Not in Farcaster context
19+
setIsInFarcaster(false);
20+
} finally {
21+
setIsLoading(false);
22+
}
23+
};
24+
25+
checkFarcasterContext();
26+
}, []);
27+
28+
return { isInFarcaster, isLoading };
29+
}

0 commit comments

Comments
 (0)