feat: useTx hook for on-chain transactions

This commit is contained in:
thesn10
2026-06-25 19:12:19 +02:00
parent f30a0eb823
commit 1adabf3aac

52
app/src/hooks/useTx.ts Normal file
View File

@@ -0,0 +1,52 @@
import {
pipe,
createTransactionMessage,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstructions,
signTransactionMessageWithSigners,
sendAndConfirmTransactionFactory,
assertIsTransactionWithBlockhashLifetime,
} from '@solana/kit'
import { useKitTransactionSigner, useSolanaClient } from '@solana/connector/react'
import { useQueryClient } from '@tanstack/react-query'
import { useToast } from '@/components/ui/Toast'
type AnyInstruction = Parameters<typeof appendTransactionMessageInstructions>[0][number]
export function useTx() {
const { signer } = useKitTransactionSigner()
const { client } = useSolanaClient()
const queryClient = useQueryClient()
const toast = useToast()
return async (
instructions: AnyInstruction[],
invalidateKeys: string[][],
label: string,
): Promise<void> => {
if (!signer || !client) throw new Error('Wallet not connected')
const { rpc, rpcSubscriptions } = client
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send()
const txMsg = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(signer, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) => appendTransactionMessageInstructions(instructions, tx),
)
const signed = await signTransactionMessageWithSigners(txMsg)
assertIsTransactionWithBlockhashLifetime(signed)
await sendAndConfirmTransactionFactory({ rpc: rpc as never, rpcSubscriptions: rpcSubscriptions as never })(
signed as never,
{ commitment: 'confirmed' },
)
toast(`Tx confirmed — ${label}`)
for (const key of invalidateKeys) {
queryClient.invalidateQueries({ queryKey: key })
}
}
}