-
Notifications
You must be signed in to change notification settings - Fork 13
feat: Add Farcaster miniapp support for identity verification flow #10 #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 36 commits
25ee077
42fc37e
9557dce
42e08a9
64d56a8
3323d82
8bff2fe
f3940b2
53564da
60eb1cb
c105e1b
e10b584
8edaca1
c34de25
f6889fd
8616d89
36dfa32
5ed0e06
5bdab21
cd6d40f
f1e9b8d
b7de6cb
304c15a
9841794
d19d211
158465a
4060809
e6ba4d0
8cf55a7
c1486dc
04ff59c
3dd1832
59484bc
f620a1c
c38476f
20d0905
9a9dbbc
7a7a921
994b4f3
75a9b45
6377bf0
359e2c2
4ad2886
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,4 +10,4 @@ | |
| <div id="app"></div> | ||
| <script type="module" src="/src/main.tsx"></script> | ||
| </body> | ||
| </html> | ||
| </html> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,13 +3,7 @@ import { Button } from "tamagui" | |
| import { useIdentitySDK } from "@goodsdks/react-hooks" | ||
| import { useAccount } from "wagmi" | ||
|
|
||
| interface VerifyButtonProps { | ||
| onVerificationSuccess: () => void | ||
| } | ||
|
|
||
| export const VerifyButton: React.FC<VerifyButtonProps> = ({ | ||
| onVerificationSuccess, | ||
| }) => { | ||
| export const VerifyButton: React.FC = () => { | ||
| const { address } = useAccount() | ||
| const { sdk: identitySDK } = useIdentitySDK("development") | ||
|
|
||
|
|
@@ -24,9 +18,8 @@ export const VerifyButton: React.FC<VerifyButtonProps> = ({ | |
| ) | ||
|
|
||
| window.location.href = fvLink | ||
| } catch (error) { | ||
| console.error("Verification failed:", error) | ||
| // Handle error (e.g., show toast) | ||
| } catch { | ||
|
||
| // Silent fail - error will be caught by the identity SDK | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,4 +31,4 @@ export default defineConfig({ | |
| "process.browser": true, | ||
| "process.env": process.env, | ||
| }, | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,4 +25,4 @@ export default defineConfig({ | |
| "process.browser": true, | ||
| "process.env": process.env, | ||
| }, | ||
| }) | ||
| }) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,7 @@ | |
| "wagmi": "*" | ||
| }, | ||
| "dependencies": { | ||
| "@farcaster/miniapp-sdk": "^0.1.8", | ||
|
||
| "lz-string": "^1.5.0", | ||
| "tsup": "^8.4.0" | ||
| }, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,25 @@ export const Envs: Record<string, Record<string, string>> = { | |
| }, | ||
| } | ||
|
|
||
| /** | ||
|
||
| * Farcaster Mini App configurations for different environments | ||
| * You need to replace these with your actual Farcaster app IDs and slugs from the Farcaster Developer Portal | ||
| */ | ||
| export const FarcasterAppConfigs: Record<string, { appId: string; appSlug: string }> = { | ||
|
||
| production: { | ||
| appId: "your-production-app-id", // Replace with actual app ID from Farcaster Developer Portal | ||
| appSlug: "gooddollar-identity", // Replace with actual app slug | ||
| }, | ||
| staging: { | ||
| appId: "your-staging-app-id", // Replace with actual app ID from Farcaster Developer Portal | ||
| appSlug: "gooddollar-identity-staging", // Replace with actual app slug | ||
| }, | ||
| development: { | ||
| appId: "your-development-app-id", // Replace with actual app ID from Farcaster Developer Portal | ||
| appSlug: "gooddollar-identity-dev", // Replace with actual app slug | ||
| }, | ||
| } | ||
|
|
||
| export interface ContractAddresses { | ||
| identityContract: `0x${string}` | ||
| ubiContract: `0x${string}` | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,4 @@ | ||
| export * from "./sdks" | ||
| export * from "./constants" | ||
| export * from "./utils/auth" | ||
|
|
| 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" |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -7,6 +7,7 @@ import { | |||
| type WalletClient, | ||||
| ContractFunctionExecutionError, | ||||
| TransactionReceipt, | ||||
| zeroAddress, | ||||
| } from "viem" | ||||
|
|
||||
| import { waitForTransactionReceipt } from "viem/actions" | ||||
|
|
@@ -20,9 +21,15 @@ import { | |||
| faucetABI, | ||||
| isSupportedChain, | ||||
| ubiSchemeV2ABI, | ||||
| FarcasterAppConfigs, | ||||
| } from "../constants" | ||||
| import type { ContractAddresses } from "../constants" | ||||
| import { resolveChainAndContract } from "../utils/chains" | ||||
| import { | ||||
| createVerificationCallbackUrl, | ||||
| createFarcasterCallbackUniversalLink, | ||||
| isInFarcasterMiniApp | ||||
| } from "../utils/auth" | ||||
| import { triggerFaucet as triggerFaucetUtil } from "../utils/triggerFaucet" | ||||
| import { | ||||
| createRpcIteratorRegistry, | ||||
|
|
@@ -82,7 +89,7 @@ export class ClaimSDK { | |||
| private readonly faucetAddress: Address | ||||
| private readonly account: Address | ||||
| private readonly env: contractEnv | ||||
| public readonly rdu: string | ||||
| public rdu: string | ||||
|
|
||||
| constructor({ | ||||
| account, | ||||
|
|
@@ -99,9 +106,11 @@ export class ClaimSDK { | |||
| this.walletClient = walletClient | ||||
| this.identitySDK = identitySDK | ||||
| this.account = account ?? walletClient.account.address | ||||
| this.env = env | ||||
|
|
||||
| // Initialize callback URL - will be set properly in initializeCallbackUrl | ||||
| this.rdu = rdu | ||||
| this.env = env | ||||
| this.initializeCallbackUrl(rdu); | ||||
|
|
||||
| const { chainId, contractEnvAddresses } = resolveChainAndContract( | ||||
| walletClient, | ||||
|
|
@@ -142,6 +151,37 @@ export class ClaimSDK { | |||
| this.faucetAddress = contractEnvAddresses.faucetContract as Address | ||||
| } | ||||
|
|
||||
| /** | ||||
| * Initialize the callback URL with proper Farcaster Universal Link support | ||||
| * @param rdu - The redirect URL after claim | ||||
| */ | ||||
| private async initializeCallbackUrl(rdu?: string): Promise<void> { | ||||
|
||||
| if (!rdu) return; | ||||
|
|
||||
| try { | ||||
| // Check if we're in a Farcaster context and should use Universal Links | ||||
| const isFarcaster = await isInFarcasterMiniApp(); | ||||
|
|
||||
| if (isFarcaster && FarcasterAppConfigs[this.env]) { | ||||
| // Create proper Farcaster Universal Link | ||||
| const farcasterConfig = FarcasterAppConfigs[this.env]; | ||||
| this.rdu = createFarcasterCallbackUniversalLink( | ||||
| farcasterConfig, | ||||
| 'claim', | ||||
| { source: "gooddollar_claim_verification" } | ||||
| ); | ||||
| } else { | ||||
| // Fallback to direct callback URL for non-Farcaster environments | ||||
| this.rdu = await createVerificationCallbackUrl(rdu, { | ||||
| source: "gooddollar_claim_verification" | ||||
| }); | ||||
| } | ||||
| } catch (error) { | ||||
| // Fallback to original URL on error | ||||
| this.rdu = rdu; | ||||
| } | ||||
| } | ||||
|
|
||||
| private getContractsForChain(chainId: SupportedChains): ContractAddresses { | ||||
| const contracts = this.chainContracts.get(chainId) | ||||
|
|
||||
|
|
@@ -417,7 +457,13 @@ export class ClaimSDK { | |||
| const { isWhitelisted } = | ||||
| await this.identitySDK.getWhitelistedRoot(userAddress) | ||||
| if (!isWhitelisted) { | ||||
| await this.fvRedirect() | ||||
| // Use IdentitySDK's navigation method to eliminate code duplication | ||||
|
||||
| // Use IdentitySDK's navigation method to eliminate code duplication |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comments should not describe changes done for a commit.
it should explain current behavior, possibly edge-cases or why something has been done in a particular way.
Thats why my suggestion
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- what duplication is being handled here exactly?
- if you choose to do a refactor, always make sure functionality does not change along the way
You introduce: hardcoded chain-id, different behavior of reloading page etc.
Its not necessarily a bad idea to move handling of face-verification to the identity-sdk.
but it should always be trippled checked against exisiting flows.
how would this affect dapps that already have this flow?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- chainid should not be hardcoded to celo
- Flow should stay the same as it was, changes needed for your flow should only affect your intended flow
And include a demo that this change works as expected, as I am not sure this is the way to handle pop-up window (fallbackToNewTab? should it not just close the pop-up window?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe the setIsWhitelisted should have been added in the catch but there is no reason to remove the error log