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