Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions apps/demo-identity-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"format": "prettier --write ."
},
"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.

this should be devdep/peerdep

Copy link
Collaborator

Choose a reason for hiding this comment

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

@vortex-hue this is not done

"@goodsdks/citizen-sdk": "*",
"@goodsdks/react-hooks": "*",
"@reown/appkit": "^1.7.2",
Expand Down
48 changes: 43 additions & 5 deletions apps/demo-identity-app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { config } from "@tamagui/config/v3"
import { useLocation } from "react-router-dom"
import { useAccount } from "wagmi"
import { useIdentitySDK } from "@goodsdks/react-hooks"
import { handleVerificationResponse, isInFarcasterMiniApp, isInFarcasterMiniAppSync } from "@goodsdks/citizen-sdk"

import { VerifyButton } from "./components/VerifyButton"
import { IdentityCard } from "./components/IdentityCard"
Expand All @@ -31,6 +32,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,13 +42,33 @@ 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")

if (verified === "true") {
// 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())
}
}

checkFarcasterMode()

// Use the new verification response handler
const verificationResult = handleVerificationResponse()

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

// Log additional verification parameters for debugging
if (verificationResult.params.size > 0) {
console.log("Verification response parameters:", Object.fromEntries(verificationResult.params))
}
}, [location.search])

//ref: https://github.com/wevm/wagmi/discussions/1806#discussioncomment-12130996
Expand Down Expand Up @@ -108,6 +130,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 +301,4 @@ const App: React.FC = () => {
)
}

export default App
export default App
12 changes: 6 additions & 6 deletions apps/demo-identity-app/src/components/VerifyButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useIdentitySDK } from "@goodsdks/react-hooks"
import { useAccount } from "wagmi"

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

export const VerifyButton: React.FC<VerifyButtonProps> = ({
Expand All @@ -17,13 +17,13 @@ export const VerifyButton: React.FC<VerifyButtonProps> = ({
if (!identitySDK || !address) return

try {
const fvLink = await identitySDK.generateFVLink(
// Use the SDK's navigation method which now uses the shared utility
await identitySDK.navigateToFaceVerification(
false,
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
onVerificationSuccess?.()
} catch (error) {
console.error("Verification failed:", error)
// Handle error (e.g., show toast)
Expand All @@ -42,4 +42,4 @@ export const VerifyButton: React.FC<VerifyButtonProps> = ({
Verify Me
</Button>
)
}
}
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
25 changes: 24 additions & 1 deletion apps/demo-identity-app/vite.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { defineConfig } from "vite";
import path from "path";
import react from "@vitejs/plugin-react";
import fs from "fs";
import { builtinModules } from "module";

let https: any;
if (process.env.HTTPS === "true") {
Expand All @@ -13,6 +14,19 @@ if (process.env.HTTPS === "true") {
https = false;
}

const nodeBuiltins = [
...builtinModules,
...builtinModules.map((m) => `node:${m}`)
];

const nodeBuiltinGlobals = nodeBuiltins.reduce((acc, name) => {
// Strip the `node:` prefix for the global key if present
const key = name.startsWith('node:') ? name.slice(5) : name
// Map both `foo` and `node:foo` → global `foo`
acc[name] = key
return acc
}, {} as Record<string, string>);

export default defineConfig({
resolve: {
dedupe: ["react", "react-dom", "wagmi", "viem"],
Expand All @@ -29,6 +43,15 @@ export default defineConfig({
plugins: [react()],
define: {
"process.browser": true,
"process.env": process.env,
// Only define specific env vars instead of the entire process.env object
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "development"),
},
build: {
rollupOptions: {
external: nodeBuiltins,
output: {
globals: nodeBuiltinGlobals
}
}
}
});
25 changes: 24 additions & 1 deletion apps/demo-webcomponents/vite.config.mts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { defineConfig } from "vite"
import path from "path"
import fs from "fs"
import { builtinModules } from "module"

let https: any
if (process.env.HTTPS === "true") {
Expand All @@ -12,6 +13,19 @@ if (process.env.HTTPS === "true") {
https = false
}

const nodeBuiltins = [
...builtinModules,
...builtinModules.map((m) => `node:${m}`)
]

const nodeBuiltinGlobals = nodeBuiltins.reduce((acc, name) => {
// Strip the `node:` prefix for the global key if present
const key = name.startsWith('node:') ? name.slice(5) : name
// Map both `foo` and `node:foo` → global `foo`
acc[name] = key
return acc
}, {} as Record<string, string>)

export default defineConfig({
resolve: {
alias: {
Expand All @@ -23,6 +37,15 @@ export default defineConfig({
},
define: {
"process.browser": true,
"process.env": process.env,
// Only define specific env vars instead of the entire process.env object
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "development"),
},
build: {
rollupOptions: {
external: nodeBuiltins,
output: {
globals: nodeBuiltinGlobals
}
}
}
})
41 changes: 41 additions & 0 deletions packages/build-config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { builtinModules } from "module"

/**
* Generate list of Node.js built-in modules for external configuration
* Includes both standard names and node: prefixed versions
*/
export function getNodeBuiltins(): string[] {
return [
...builtinModules,
...builtinModules.map((m) => `node:${m}`)
]
}

/**
* Generate globals mapping for Node.js built-ins
* Maps both `foo` and `node:foo` to global `foo`
*/
export function getNodeBuiltinGlobals(): Record<string, string> {
const builtins = getNodeBuiltins()
return builtins.reduce((acc, name) => {
// Strip the `node:` prefix for the global key if present
const key = name.startsWith('node:') ? name.slice(5) : name
// Map both `foo` and `node:foo` → global `foo`
acc[name] = key
return acc
}, {} as Record<string, string>)
}

/**
* Common external dependencies for browser builds
*/
export const COMMON_EXTERNALS = [
"@goodsdks/citizen-sdk",
"viem",
...getNodeBuiltins()
]

/**
* Regex pattern to match all node: imports
*/
export const NODE_MODULES_REGEX = /^node:/
14 changes: 14 additions & 0 deletions packages/build-config/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "@repo/build-config",
"version": "0.0.0",
"type": "module",
"private": true,
"main": "./index.ts",
"exports": {
".": "./index.ts"
},
"devDependencies": {
"@types/node": "^20.0.0",
"typescript": "^5.0.0"
}
}
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"
export * from "./utils/farcaster-navigation"
12 changes: 3 additions & 9 deletions packages/citizen-sdk/src/sdks/viem-claim-sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,18 +266,12 @@ export class ClaimSDK {
}

/**
* Redirects the user through the face-verification flow.
* Redirects the user through the face-verification flow with Farcaster support.
* @throws If face verification redirect fails.
*/
private async fvRedirect(): Promise<void> {
const fvLink = await this.identitySDK.generateFVLink(false, this.rdu, 42220)
if (typeof window !== "undefined") {
window.location.href = fvLink
} else {
throw new Error(
"Face verification redirect is only supported in browser environments.",
)
}
// Use the new navigation method that handles Farcaster automatically
await this.identitySDK.navigateToFaceVerification(false, this.rdu, 42220)
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/citizen-sdk/src/sdks/viem-custodial-claim-sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {

import { waitForTransactionReceipt } from "viem/actions"
import { ClaimSDK, type ClaimSDKOptions } from "./viem-claim-sdk" // Import the base ClaimSDK
import type { WalletClaimStatus } from "../types"
import type { WalletClaimStatus } from "./viem-claim-sdk"

interface ClaimCustodialSDKOptions extends Omit<ClaimSDKOptions, 'account'> {
// Remove account from the options since we'll get it from walletClient
Expand Down
11 changes: 10 additions & 1 deletion packages/citizen-sdk/src/sdks/viem-custodial-identity-sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export class IdentityCustodialSDK extends IdentitySDK {
popupMode: boolean = false,
callbackUrl?: string,
chainId?: number,
useFarcasterNavigation?: boolean,
): Promise<string> {
try {
const account = this.walletClient.account
Expand Down Expand Up @@ -108,7 +109,15 @@ export class IdentityCustodialSDK extends IdentitySDK {
}

if (callbackUrl) {
params[popupMode ? "cbu" : "rdu"] = callbackUrl
// Import utility functions for universal link support
const { createUniversalLinkCallback } = await import("../utils/auth")

// Create universal link compatible callback for mobile/native support
const universalCallbackUrl = createUniversalLinkCallback(callbackUrl, {
source: "gooddollar_identity_verification"
})

params[popupMode ? "cbu" : "rdu"] = universalCallbackUrl
}

url.searchParams.append(
Expand Down
Loading