"use client";
import { AnchorProvider, Program } from "@coral-xyz/anchor";
import { useDynamicContext } from "@dynamic-labs/sdk-react-core";
import { isSolanaWallet } from "@dynamic-labs/solana";
import { Connection, PublicKey } from "@solana/web3.js";
import {
createContext,
ReactNode,
useCallback,
useContext,
useEffect,
useMemo,
useState,
} from "react";
// Import your program's types and IDL
import { YourProgram } from './path-to-your-program-types';
import yourProgramIdl from './path-to-your-idl.json';
interface AnchorProviderContextValue {
program: Program<YourProgram> | null;
connection: Connection | null;
provider: AnchorProvider | null;
publicKey: PublicKey | null;
}
const AnchorProviderContext = createContext<AnchorProviderContextValue>({
program: null,
connection: null,
provider: null,
publicKey: null,
});
export function useAnchorProvider() {
return useContext(AnchorProviderContext);
}
interface AnchorProviderProps {
children: ReactNode;
}
export default function AnchorProviderComponent({ children }: AnchorProviderProps) {
const { primaryWallet, sdkHasLoaded } = useDynamicContext();
const [connection, setConnection] = useState<Connection | null>(null);
const [provider, setProvider] = useState<AnchorProvider | null>(null);
const [program, setProgram] = useState<Program<YourProgram> | null>(null);
// Derive the public key from the connected wallet
const publicKey = useMemo(() => {
if (!primaryWallet?.address) return null;
try {
return new PublicKey(primaryWallet.address);
} catch (error) {
console.error("Invalid public key:", error);
return null;
}
}, [primaryWallet?.address]);
// Initialize Anchor when wallet or SDK state changes
const initAnchor = useCallback(async () => {
if (!primaryWallet || !sdkHasLoaded || !publicKey) {
setConnection(null);
setProvider(null);
setProgram(null);
return;
}
try {
if (!isSolanaWallet(primaryWallet)) {
console.error("Primary wallet is not a Solana wallet");
return;
}
const newConnection = await primaryWallet.getConnection();
const signer = await primaryWallet.getSigner();
const newProvider = new AnchorProvider(
newConnection,
{
publicKey,
signTransaction: async (tx) => signer.signTransaction(tx),
signAllTransactions: async (txs) => signer.signAllTransactions(txs),
},
{
commitment: "confirmed",
skipPreflight: true,
}
);
const newProgram = new Program<YourProgram>(yourProgramIdl, newProvider);
setConnection(newConnection);
setProvider(newProvider);
setProgram(newProgram);
} catch (error) {
console.error("Error initializing Anchor provider:", error);
setConnection(null);
setProvider(null);
setProgram(null);
}
}, [primaryWallet, sdkHasLoaded, publicKey]);
useEffect(() => {
initAnchor();
}, [initAnchor]);
const contextValue = useMemo(
() => ({
program,
connection,
provider,
publicKey,
}),
[program, connection, provider, publicKey]
);
return (
<AnchorProviderContext.Provider value={contextValue}>
{children}
</AnchorProviderContext.Provider>
);
}