import { useCallback, useMemo, useState } from 'react'
import { useConnection, useWallet } from '@solana/wallet-adapter-react'
import { web3 } from '@coral-xyz/anchor'
import { BN, getProgram } from '@/lib/anchor-client'
export function useProgram() {
const { connection } = useConnection()
const wallet = useWallet()
const [loading, setLoading] = useState(false)
const [error, setError] = useState<Error | null>(null)
const program = useMemo(() => {
if (!wallet.publicKey || !wallet.signTransaction) return null
return getProgram(connection, wallet as any)
}, [connection, wallet.publicKey, wallet.signTransaction])
const pda = useMemo(() => {
if (!wallet.publicKey || !program) return null
const [addr] = web3.PublicKey.findProgramAddressSync(
[Buffer.from('state'), wallet.publicKey.toBuffer()],
program.programId
)
return addr
}, [wallet.publicKey, program])
const initialize = useCallback(async () => {
if (!program || !wallet.publicKey || !pda) throw new Error('Wallet or program not ready')
setLoading(true)
setError(null)
try {
const txSig = await program.methods.initialize().accounts({
authority: wallet.publicKey,
state: pda,
systemProgram: web3.SystemProgram.programId,
}).rpc()
return txSig
} catch (e: any) {
setError(e)
throw e
} finally { setLoading(false) }
}, [program, wallet.publicKey, pda])
const update = useCallback(async (value: number) => {
if (!program || !wallet.publicKey || !pda) throw new Error('Wallet or program not ready')
setLoading(true)
setError(null)
try {
const txSig = await program.methods.update(new BN(value)).accounts({
authority: wallet.publicKey,
state: pda,
}).rpc()
return txSig
} catch (e: any) {
setError(e)
throw e
} finally { setLoading(false) }
}, [program, wallet.publicKey, pda])
const fetchState = useCallback(async () => {
if (!program || !pda) throw new Error('Program not ready')
return await program.account.state.fetch(pda)
}, [program, pda])
return { program, pda, initialize, update, fetchState, loading, error }
}