mirror of
https://github.com/neynarxyz/create-farcaster-mini-app.git
synced 2025-12-11 11:52:35 -05:00
feat: add support for coinbase wallet with auto connect and metamask
This commit is contained in:
@@ -8,6 +8,13 @@ import React from "react";
|
||||
interface FrameContextType {
|
||||
isSDKLoaded: boolean;
|
||||
context: Context.FrameContext | undefined;
|
||||
openUrl: (url: string) => Promise<void>;
|
||||
close: () => Promise<void>;
|
||||
added: boolean;
|
||||
notificationDetails: FrameNotificationDetails | null;
|
||||
lastEvent: string;
|
||||
addFrame: () => Promise<void>;
|
||||
addFrameResult: string;
|
||||
}
|
||||
|
||||
const FrameContext = React.createContext<FrameContextType | undefined>(undefined);
|
||||
@@ -20,10 +27,26 @@ export function useFrame() {
|
||||
const [lastEvent, setLastEvent] = useState("");
|
||||
const [addFrameResult, setAddFrameResult] = useState("");
|
||||
|
||||
// SDK actions only work in mini app clients, so this pattern supports browser actions as well
|
||||
const openUrl = useCallback(async (url: string) => {
|
||||
if (context) {
|
||||
await sdk.actions.openUrl(url);
|
||||
} else {
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
}, [context]);
|
||||
|
||||
const close = useCallback(async () => {
|
||||
if (context) {
|
||||
await sdk.actions.close();
|
||||
} else {
|
||||
window.close();
|
||||
}
|
||||
}, [context]);
|
||||
|
||||
const addFrame = useCallback(async () => {
|
||||
try {
|
||||
setNotificationDetails(null);
|
||||
|
||||
const result = await sdk.actions.addFrame();
|
||||
|
||||
if (result.notificationDetails) {
|
||||
@@ -35,15 +58,11 @@ export function useFrame() {
|
||||
: "Added, got no notification details"
|
||||
);
|
||||
} catch (error) {
|
||||
if (error instanceof AddFrame.RejectedByUser) {
|
||||
if (error instanceof AddFrame.RejectedByUser || error instanceof AddFrame.InvalidDomainManifest) {
|
||||
setAddFrameResult(`Not added: ${error.message}`);
|
||||
}else {
|
||||
setAddFrameResult(`Error: ${error}`);
|
||||
}
|
||||
|
||||
if (error instanceof AddFrame.InvalidDomainManifest) {
|
||||
setAddFrameResult(`Not added: ${error.message}`);
|
||||
}
|
||||
|
||||
setAddFrameResult(`Error: ${error}`);
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -111,18 +130,28 @@ export function useFrame() {
|
||||
}
|
||||
}, [isSDKLoaded]);
|
||||
|
||||
return { isSDKLoaded, context, added, notificationDetails, lastEvent, addFrame, addFrameResult };
|
||||
return {
|
||||
isSDKLoaded,
|
||||
context,
|
||||
added,
|
||||
notificationDetails,
|
||||
lastEvent,
|
||||
addFrame,
|
||||
addFrameResult,
|
||||
openUrl,
|
||||
close,
|
||||
};
|
||||
}
|
||||
|
||||
export function FrameProvider({ children }: { children: React.ReactNode }) {
|
||||
const { isSDKLoaded, context } = useFrame();
|
||||
const frameContext = useFrame();
|
||||
|
||||
if (!isSDKLoaded) {
|
||||
if (!frameContext.isSDKLoaded) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<FrameContext.Provider value={{ isSDKLoaded, context }}>
|
||||
<FrameContext.Provider value={frameContext}>
|
||||
{children}
|
||||
</FrameContext.Provider>
|
||||
);
|
||||
|
||||
@@ -4,6 +4,42 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { farcasterFrame } from "@farcaster/frame-wagmi-connector";
|
||||
import { coinbaseWallet, metaMask } from 'wagmi/connectors';
|
||||
import { APP_NAME, APP_ICON_URL, APP_URL } from "~/lib/constants";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useConnect, useAccount } from "wagmi";
|
||||
import React from "react";
|
||||
|
||||
// Custom hook for Coinbase Wallet detection and auto-connection
|
||||
function useCoinbaseWalletAutoConnect() {
|
||||
const [isCoinbaseWallet, setIsCoinbaseWallet] = useState(false);
|
||||
const { connect, connectors } = useConnect();
|
||||
const { isConnected } = useAccount();
|
||||
|
||||
useEffect(() => {
|
||||
// Check if we're running in Coinbase Wallet
|
||||
const checkCoinbaseWallet = () => {
|
||||
const isInCoinbaseWallet = window.ethereum?.isCoinbaseWallet ||
|
||||
window.ethereum?.isCoinbaseWalletExtension ||
|
||||
window.ethereum?.isCoinbaseWalletBrowser;
|
||||
setIsCoinbaseWallet(!!isInCoinbaseWallet);
|
||||
};
|
||||
|
||||
checkCoinbaseWallet();
|
||||
window.addEventListener('ethereum#initialized', checkCoinbaseWallet);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('ethereum#initialized', checkCoinbaseWallet);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Auto-connect if in Coinbase Wallet and not already connected
|
||||
if (isCoinbaseWallet && !isConnected) {
|
||||
connect({ connector: connectors[1] }); // Coinbase Wallet connector
|
||||
}
|
||||
}, [isCoinbaseWallet, isConnected, connect, connectors]);
|
||||
|
||||
return isCoinbaseWallet;
|
||||
}
|
||||
|
||||
export const config = createConfig({
|
||||
chains: [base, optimism, mainnet, degen, unichain],
|
||||
@@ -32,10 +68,20 @@ export const config = createConfig({
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
// Wrapper component that provides Coinbase Wallet auto-connection
|
||||
function CoinbaseWalletAutoConnect({ children }: { children: React.ReactNode }) {
|
||||
useCoinbaseWalletAutoConnect();
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
export default function Provider({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<WagmiProvider config={config}>
|
||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<CoinbaseWalletAutoConnect>
|
||||
{children}
|
||||
</CoinbaseWalletAutoConnect>
|
||||
</QueryClientProvider>
|
||||
</WagmiProvider>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user