Skip to content
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
25ee077
Feat: Installed farcaster package
vortex-hue Aug 13, 2025
42fc37e
fix: build errors
vortex-hue Aug 14, 2025
9557dce
feat: Add Farcaster miniapp support for identity flow with build fixes
vortex-hue Aug 14, 2025
42e08a9
rm eslintrc
vortex-hue Aug 14, 2025
64d56a8
refactor: Address code review feedback with improved architecture acr…
vortex-hue Aug 14, 2025
3323d82
fix: Address code review complaints
vortex-hue Aug 16, 2025
8bff2fe
fix: working on resolving the reviews made
vortex-hue Aug 18, 2025
f3940b2
fix: removed dynamic import, and reverted some configs to the default…
vortex-hue Aug 19, 2025
53564da
pulled update
vortex-hue Aug 28, 2025
60eb1cb
fix: Addressed all outstanding code review feedback.
vortex-hue Sep 2, 2025
c105e1b
fix: resolved all code changes requested
vortex-hue Sep 2, 2025
e10b584
feat: implement shared build config utility for Node.js built-ins and…
vortex-hue Sep 2, 2025
8edaca1
revert: removed the shared build config changes and other changes
vortex-hue Sep 3, 2025
c34de25
fc:frame meta tag
vortex-hue Sep 5, 2025
f6889fd
fix: refined the codebase
vortex-hue Sep 5, 2025
8616d89
fix:patching up the codebase
vortex-hue Sep 8, 2025
36dfa32
Revert "fix:patching up the codebase"
vortex-hue Sep 8, 2025
5ed0e06
revert: reverted all changes requested
vortex-hue Sep 8, 2025
5bdab21
revert: reverted all changes requested
vortex-hue Sep 8, 2025
cd6d40f
revert: reverted all changes requested
vortex-hue Sep 8, 2025
f1e9b8d
fix: revert changes requested
vortex-hue Sep 13, 2025
b7de6cb
fix: revert changes requested
vortex-hue Sep 13, 2025
304c15a
fix: revert changes affecting mobile
vortex-hue Sep 18, 2025
9841794
feat: implemented the universal link using farcaster docs
vortex-hue Sep 22, 2025
d19d211
fix: resolving previous issues
vortex-hue Oct 4, 2025
158465a
fix: resolved redirection concerns and fixed bugs
vortex-hue Oct 4, 2025
4060809
Merge remote-tracking branch 'origin/main' into add-farcaster-support…
vortex-hue Oct 9, 2025
e6ba4d0
fix: build id working well now
vortex-hue Oct 25, 2025
8cf55a7
fix: remove the unused interface of VerifyButtonProps
vortex-hue Oct 25, 2025
c1486dc
fix: removed the used import { createUniversalLinkCallback } from ../…
vortex-hue Oct 25, 2025
04ff59c
fix: revert apps/demo-identity-app/src/App.tsx and verifybutton.tsx t…
vortex-hue Oct 25, 2025
3dd1832
Merge upstream/main into add-farcaster-support-for-the-identity-flow
vortex-hue Nov 10, 2025
59484bc
fix: update auth.ts to use chainConfigs instead of contractAddresses
vortex-hue Nov 10, 2025
f620a1c
Merge remote-tracking branch 'upstream/main' into add-farcaster-suppo…
vortex-hue Dec 16, 2025
c38476f
refactor: apply engineering principles to Farcaster implementation
vortex-hue Dec 16, 2025
20d0905
refactor: clean up demo app following engineering principles
vortex-hue Dec 16, 2025
9a9dbbc
fix: address code review feedback
vortex-hue Dec 28, 2025
7a7a921
fix: address round 3 code review comments (restore comments, fix fvRe…
vortex-hue Dec 28, 2025
994b4f3
fix: address PR review feedback from L03TJ3
vortex-hue Feb 10, 2026
75a9b45
fix: address round 2 PR review feedback from sirpy
vortex-hue Feb 16, 2026
6377bf0
chore: merge upstream/main and regenerate yarn.lock
vortex-hue Feb 16, 2026
359e2c2
feat: add navigateToFaceVerification with Farcaster-aware redirect
vortex-hue Feb 16, 2026
4ad2886
refactor: remove Farcaster config coupling from SDK internals
vortex-hue Feb 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/demo-identity-app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
<div id="app"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
</html>
2 changes: 1 addition & 1 deletion apps/demo-identity-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@
"typescript": "^5.8.2",
"vite": "6.3.5"
}
}
}
187 changes: 179 additions & 8 deletions apps/demo-identity-app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ import { config } from "@tamagui/config/v3"
import { useLocation } from "react-router-dom"
import { useAccount } from "wagmi"
import { useIdentitySDK } from "@goodsdks/react-hooks"
import { handleVerificationResponse, handleVerificationResponseSync, isInFarcasterMiniApp, isInFarcasterMiniAppSync } from "@goodsdks/citizen-sdk"

import { VerifyButton } from "./components/VerifyButton"
import { IdentityCard } from "./components/IdentityCard"
import { SigningModal } from "./components/SigningModal"
import { ClaimButton } from "./components/ClaimButton"
import { sdk } from '@farcaster/miniapp-sdk'

const tamaguiConfig = createTamagui(config)

Expand All @@ -31,6 +33,7 @@ const App: React.FC = () => {
const [loadingWhitelist, setLoadingWhitelist] = useState<boolean | undefined>(
undefined,
)
const [isFarcasterMode, setIsFarcasterMode] = useState<boolean>(false)

const location = useLocation()
const { address, isConnected } = useAccount()
Expand All @@ -40,14 +43,166 @@ const App: React.FC = () => {
const { sdk: identitySDK } = useIdentitySDK("development")

useEffect(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. clean this up. if we want to show someone how the sdk could be implemented, this is not easy to follow
  2. perhaps consider making it part of the VerifyButton.tsx ?
  3. include a README with examples in citizen-sdk for how it works/should be implemented

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Lewis, I don't fully understand this, mind explaining deeper please?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you mean I should revert the file to how it was initially? and remove every code I added relating to the forecaster support?

const urlParams = new URLSearchParams(location.search)
const verified = urlParams.get("verified")
// Initialize Farcaster SDK
const initializeFarcasterSDK = async () => {
try {
await sdk.actions.ready()
//console.log('Farcaster SDK initialized successfully')

// Enable back navigation for Farcaster miniapp
try {
await sdk.back.enableWebNavigation()
//console.log('Farcaster back navigation enabled')
} catch (backError) {
//console.warn('Failed to enable Farcaster back navigation:', backError)
}
} catch (error) {
//console.warn('Failed to initialize Farcaster SDK:', error)
}
}

// Check if running in Farcaster miniapp mode (async)
const checkFarcasterMode = async () => {
try {
const isFarcaster = await isInFarcasterMiniApp()
setIsFarcasterMode(isFarcaster)
} catch (error) {
// Fallback to sync version if async fails
//console.warn('Async Farcaster detection failed, using sync fallback:', error)
setIsFarcasterMode(isInFarcasterMiniAppSync())
}
}

// Handle verification response with proper async support and error handling
const handleVerification = async () => {
try {
const result = await handleVerificationResponse(
window.location.href,
address,
identitySDK?.publicClient,
42220,
"development"
);

if (result.isVerified) {
setIsVerified(true);
// Clean up URL parameters
window.history.replaceState({}, document.title, window.location.pathname);
}

// Log additional verification parameters for debugging
if (result.params.size > 0) {
//console.log("Verification response parameters:", Object.fromEntries(result.params));
}

// Log verification details for debugging
// console.log("Verification result:", {
// isVerified: result.isVerified,
// verified: result.verified,
// onChainVerified: result.onChainVerified
// });
} catch (error) {
//console.error('Verification response error:', error);
// Fallback to sync version if async fails
try {
const syncResult = handleVerificationResponseSync();
if (syncResult.isVerified) {
setIsVerified(true);
window.history.replaceState({}, document.title, window.location.pathname);
}
} catch (syncError) {
//console.error('Sync verification fallback failed:', syncError);
}
}
};

initializeFarcasterSDK()
checkFarcasterMode()
handleVerification()
}, [location.search, address, identitySDK])

// Add custom back navigation handler for Farcaster
useEffect(() => {
const handleBackNavigation = () => {
if (isFarcasterMode) {
//console.log('Back navigation triggered in Farcaster mode')
// Handle back navigation logic here if needed
// For now, just log the event
}
}

if (verified === "true") {
setIsVerified(true)
window.history.replaceState({}, document.title, window.location.pathname)
// Listen for back navigation events
window.addEventListener('popstate', handleBackNavigation)

return () => {
window.removeEventListener('popstate', handleBackNavigation)
}
}, [location.search])
}, [isFarcasterMode])

// Handle verification callback for Farcaster Universal Links
useEffect(() => {
const handleVerificationCallback = () => {
// Check for verification parameters in URL (Farcaster appends these to homeUrl)
const urlParams = new URLSearchParams(window.location.search);
const hasVerificationParams = urlParams.has('verified') ||
urlParams.has('account') ||
urlParams.has('nonce') ||
urlParams.has('fvsig');

if (hasVerificationParams) {
//console.log('Verification parameters detected in URL:', Object.fromEntries(urlParams));

// Process verification response
const handleCallback = async () => {
try {
const result = await handleVerificationResponse(
window.location.href,
address,
identitySDK?.publicClient,
42220,
"development"
);

//console.log('Verification result:', result);

if (result.isVerified) {
setIsVerified(true);
//console.log('Verification successful via Farcaster Universal Link');

// Clean up URL parameters but keep the path
const cleanUrl = window.location.origin + window.location.pathname;
window.history.replaceState({}, document.title, cleanUrl);

// If in Farcaster, show back navigation
if (isFarcasterMode) {
try {
// Set up back navigation handler
sdk.back.onback = () => {
//console.log('Back navigation triggered - returning to Farcaster');
// Farcaster will handle the actual navigation
}

// Show the back control
await sdk.back.show()
//console.log('Back control shown in Farcaster');
} catch (navError) {
//console.warn('Failed to show back control in Farcaster:', navError)
}
}
} else {
//console.log('Verification failed or not completed');
}
} catch (error) {
//console.error('Verification callback error:', error)
}
};

handleCallback();
}
};

handleVerificationCallback();
}, [location.search, address, identitySDK, isFarcasterMode])

//ref: https://github.com/wevm/wagmi/discussions/1806#discussioncomment-12130996
// does not react to switch account when triggered from metamask.
Expand All @@ -72,7 +227,7 @@ const App: React.FC = () => {
setIsWhitelisted(isWhitelisted)
setIsVerified(isWhitelisted ?? false)
} catch (error) {
console.error("Error checking whitelist:", error)
//console.error("Error checking whitelist:", error)
} finally {
setLoadingWhitelist(false)
}
Expand Down Expand Up @@ -108,6 +263,22 @@ const App: React.FC = () => {
>
GoodDollar Identity Verification
</Text>

{isFarcasterMode && (
<YStack
padding="$2"
backgroundColor="#E3F2FD"
borderRadius="$3"
borderWidth={1}
borderColor="#2196F3"
marginVertical={8}
>
<Text fontSize={12} color="#1976D2" textAlign="center" fontWeight="bold">
Farcaster MiniApp Mode Detected
</Text>

</YStack>
)}

{/* Disclaimer Section */}
<YStack
Expand Down Expand Up @@ -263,4 +434,4 @@ const App: React.FC = () => {
)
}

export default App
export default App
57 changes: 36 additions & 21 deletions apps/demo-identity-app/src/components/VerifyButton.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,60 @@
import React from "react"
import { Button } from "tamagui"
import React, { useState } from "react"
import { Button, Spinner } from "tamagui"
import { useIdentitySDK } from "@goodsdks/react-hooks"
import { useAccount } from "wagmi"

interface VerifyButtonProps {
onVerificationSuccess: () => void
onVerificationSuccess?: () => void
}

export const VerifyButton: React.FC<VerifyButtonProps> = ({
onVerificationSuccess,
}) => {
const { address } = useAccount()
const { sdk: identitySDK } = useIdentitySDK("development")
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState<string | null>(null)

const handleVerify = async () => {
if (!identitySDK || !address) return

setIsLoading(true)
setError(null)

try {
const fvLink = await identitySDK.generateFVLink(
false,
// Force popup mode for better Farcaster compatibility
await identitySDK.navigateToFaceVerification(
true, // Force popup mode
window.location.href,
42220,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this removed

42220
)

window.location.href = fvLink
} catch (error) {
onVerificationSuccess?.()
} catch (error: any) {
console.error("Verification failed:", error)
// Handle error (e.g., show toast)
setError(error.message || "Verification failed. Please try again.")
} finally {
setIsLoading(false)
}
}

return (
<Button
onPress={handleVerify}
color="white"
backgroundColor="#00AEFF"
hoverStyle={{
backgroundColor: "black",
}}
>
Verify Me
</Button>
<div>
<Button
onPress={handleVerify}
disabled={isLoading}
color="white"
backgroundColor="#00AEFF"
hoverStyle={{
backgroundColor: "black",
}}
>
{isLoading ? <Spinner size="small" color="white" /> : "Verify Me"}
</Button>
{error && (
<div style={{ color: "red", fontSize: "14px", marginTop: "8px" }}>
{error}
</div>
)}
</div>
)
}
}
10 changes: 7 additions & 3 deletions apps/demo-identity-app/src/config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ import React, { ReactNode } from "react"

const queryClient = new QueryClient()

const projectId = "71dd03d057d89d0af68a4c627ec59694"

const projectId = "71dd03d057d89d0af68a4c627ec59694"
const metadata = {
name: "AppKit",
description: "AppKit Example",
url: "https://example.com", // origin must match your domain & subdomain
url: "http://localhost:3000",
icons: ["https://avatars.githubusercontent.com/u/179229932"],
}

Expand All @@ -38,6 +37,11 @@ createAppKit({
"--w3m-color-mix-strength": 40,
"--w3m-accent": "#00BB7F",
},
allowUnsupportedChain: false,
enableWalletConnect: true,
enableInjected: true,
enableEIP6963: true,
enableCoinbase: true,
})

type ComponentProps = {
Expand Down
2 changes: 2 additions & 0 deletions apps/demo-identity-app/src/globals.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import React from "react"

declare namespace JSX {
interface IntrinsicElements {
"claim-button": React.DetailedHTMLProps<
Expand Down
2 changes: 1 addition & 1 deletion apps/demo-identity-app/vite.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ export default defineConfig({
"process.browser": true,
"process.env": process.env,
},
});
});
2 changes: 1 addition & 1 deletion apps/demo-webcomponents/vite.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ export default defineConfig({
"process.browser": true,
"process.env": process.env,
},
})
})
1 change: 1 addition & 0 deletions packages/citizen-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"wagmi": "*"
},
"dependencies": {
"@farcaster/miniapp-sdk": "^0.1.8",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dev?peer? @L03TJ3

"lz-string": "^1.5.0",
"tsup": "^8.4.0"
},
Expand Down
2 changes: 2 additions & 0 deletions packages/citizen-sdk/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from "./sdks"
export * from "./constants"
export * from "./utils/auth"

1 change: 0 additions & 1 deletion packages/citizen-sdk/src/sdks/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from "./viem-identity-sdk"
export * from "./viem-claim-sdk"
export * from "./viem-custodial-claim-sdk"
export * from "./viem-custodial-identity-sdk"
Loading