feat: useTx hook for on-chain transactions
This commit is contained in:
52
app/src/hooks/useTx.ts
Normal file
52
app/src/hooks/useTx.ts
Normal 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 })
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user