
Security News
New React Server Components Vulnerabilities: DoS and Source Code Exposure
New DoS and source code exposure bugs in React Server Components and Next.js: what’s affected and how to update safely.
@solana/react
Advanced tools
This package contains React hooks for building Solana apps.
useSignIn(uiWalletAccount, chain)Given a UiWallet or UiWalletAccount this hook returns a function that you can call to trigger a wallet's ‘Sign In With Solana’ feature.
import { useSignIn } from '@solana/react';
function SignInButton({ wallet }) {
const csrfToken = useCsrfToken();
const signIn = useSignIn(wallet);
return (
<button
onClick={async () => {
try {
const { account, signedMessage, signature } = await signIn({
requestId: csrfToken,
});
// Authenticate the user, typically on the server, by verifying that
// `signedMessage` was signed by the person who holds the private key for
// `account.publicKey`.
//
// Authorize the user, also on the server, by decoding `signedMessage` as the
// text of a Sign In With Solana message, verifying that it was not modified
// from the values your application expects, and that its content is sufficient
// to grant them access.
window.alert(`You are now signed in with the address ${account.address}`);
} catch (e) {
console.error('Failed to sign in', e);
}
}}
>
Sign In
</button>
);
}
useWalletAccountMessageSigner(uiWalletAccount)Given a UiWalletAccount, this hook returns an object that conforms to the MessageModifyingSigner interface of @solana/signers.
import { useWalletAccountMessageSigner } from '@solana/react';
import { createSignableMessage } from '@solana/signers';
function SignMessageButton({ account, text }) {
const messageSigner = useWalletAccountMessageSigner(account);
return (
<button
onClick={async () => {
try {
const signableMessage = createSignableMessage(text);
const [signedMessage] = await messageSigner.modifyAndSignMessages([signableMessage]);
const messageWasModified = signableMessage.content !== signedMessage.content;
const signatureBytes = signedMessage.signatures[messageSigner.address];
window.alert(
`Signature bytes: ${signatureBytes.toString()}${
messageWasModified ? ' (message was modified)' : ''
}`,
);
} catch (e) {
console.error('Failed to sign message', e);
}
}}
>
Sign Message: {text}
</button>
);
}
[!NOTE] The type
MessageModifyingSigneris returned from this hook instead ofMessageSignerorMessagePartialSigner. This is a conservative assumption based on the fact that your application can not control whether or not the wallet will modify the message before signing it.
useWalletAccountTransactionSigner(uiWalletAccount, chain)Given a UiWalletAccount and a chain that begins with solana:, this hook returns an object that conforms to the TransactionModifyingSigner interface of @solana/signers.
import { useWalletAccountTransactionSigner } from '@solana/react';
function SignTransactionButton({ account, transaction }) {
const transactionSigner = useWalletAccountTransactionSigner(account, 'solana:devnet');
return (
<button
onClick={async () => {
try {
const [{ signatures }] = await transactionSigner.modifyAndSignTransactions([transaction]);
const signatureBytes = signatures[transactionSigner.address];
window.alert(`Signature bytes: ${signatureBytes.toString()}`);
} catch (e) {
console.error('Failed to sign transaction', e);
}
}}
>
Sign Transaction
</button>
);
}
[!NOTE] The type
TransactionModifyingSigneris returned from this hook instead ofTransactionSignerorTransactionPartialSigner. This is a conservative assumption based on the fact that your application can not control whether or not the wallet will modify the transaction before signing it (eg. to add guard instructions, or a priority fee budget).
useWalletAccountTransactionSendingSigner(uiWalletAccount, chain)Given a UiWalletAccount and a chain that begins with solana:, this hook returns an object that conforms to the TransactionSendingSigner interface of @solana/signers.
import { useWalletAccountTransactionSendingSigner } from '@solana/react';
import {
appendTransactionMessageInstruction,
createSolanaRpc,
getBase58Decoder,
pipe,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
signAndSendTransactionMessageWithSigners,
} from '@solana/kit';
function RecordMemoButton({ account, rpc, text }) {
const signer = useWalletAccountTransactionSendingSigner(account, 'solana:devnet');
return (
<button
onClick={async () => {
try {
const { value: latestBlockhash } = await createSolanaRpc('https://api.devnet.solana.com')
.getLatestBlockhash()
.send();
const message = pipe(
createTransactionMessage({ version: 'legacy' }),
m => setTransactionMessageFeePayerSigner(signer, m),
m => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
m => appendTransactionMessageInstruction(getAddMemoInstruction({ memo: text }), m),
);
const signatureBytes = await signAndSendTransactionMessageWithSigners(message);
const base58Signature = getBase58Decoder().decode(signature);
window.alert(`View transaction: https://explorer.solana.com/tx/${base58Signature}?cluster=devnet`);
} catch (e) {
console.error('Failed to record memo', e);
}
}}
>
Record Memo
</button>
);
}
useSignMessage(uiWalletAccount)Given a UiWalletAccount, this hook returns a function you can call to sign a byte array.
A config object with the following properties:
message: A Uint8Array of bytes to signAn object with the following properties:
signature: The 64-byte Ed25519 signature as a Uint8ArraysignedMessage: The Uint8Array of bytes signed by the wallet. These bytes might differ from the input bytes if the wallet modified the messageimport { useSignMessage } from '@solana/react';
function SignMessageButton({ account, messageBytes }) {
const signMessage = useSignMessage(account);
return (
<button
onClick={async () => {
try {
const { signature } = await signMessage({
message: messageBytes,
});
window.alert(`Signature bytes: ${signature.toString()}`);
} catch (e) {
console.error('Failed to sign message', e);
}
}}
>
Sign Message
</button>
);
}
useSignTransaction(uiWalletAccount, chain)Given a UiWalletAccount and a chain that begins with solana:, this hook returns a function you can call to sign a serialized transaction.
A config object with the following properties:
options: An object with the following properties:
minContextSlot: A slot at which any blockhash/nonce in the transaction is known to exist. This may be used by the signer and/or RPC to determine the validity of the blockhashes/nonces it has observed.transaction: A Uint8Array of bytes that conforms to the Solana transaction schemaAn object with the following properties:
signedTransaction: A Uint8Array of bytes that conforms to the Solana transaction schemaimport { useSignTransaction } from '@solana/react';
function SignTransactionButton({ account, transactionBytes }) {
const signTransaction = useSignTransaction(account, 'solana:devnet');
return (
<button
onClick={async () => {
try {
const { signedTransaction } = await signTransaction({
transaction: transactionBytes,
});
window.alert(`Signed transaction bytes: ${signedTransaction.toString()}`);
} catch (e) {
console.error('Failed to sign transaction', e);
}
}}
>
Sign Transaction
</button>
);
}
useSignAndSendTransaction(uiWalletAccount, chain)Given a UiWalletAccount and a chain that begins with solana:, this hook returns a function you can call to sign and send a serialized transaction.
A config object with the following properties:
options: An object with the following properties:
minContextSlot: A slot at which any blockhash/nonce in the transaction is known to exist. This may be used by the signer and/or RPC to determine the validity of the blockhashes/nonces it has observed.transaction: A Uint8Array of bytes that conforms to the Solana transaction schemaThat function returns an object with the following properties:
signature: A Uint8Array of bytes representing the signature of the sent transaction.import { getBase58Decoder } from '@solana/codecs-strings';
import { useSignAndSendTransaction } from '@solana/react';
function SignAndSendTransactionButton({ account, transactionBytes }) {
const signAndSendTransaction = useSignAndSendTransaction(account, 'solana:devnet');
return (
<button
onClick={async () => {
try {
const { signature } = await signAndSendTransaction({
transaction: transactionBytes,
});
const base58TransactionSignature = getBase58Decoder().decode(signature);
window.alert(
`View transaction: https://explorer.solana.com/tx/${base58TransactionSignature}?cluster=devnet`,
);
} catch (e) {
console.error('Failed to send transaction', e);
}
}}
>
Sign and Send Transaction
</button>
);
}
FAQs
React hooks for building Solana apps
The npm package @solana/react receives a total of 6,714 weekly downloads. As such, @solana/react popularity was classified as popular.
We found that @solana/react demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
New DoS and source code exposure bugs in React Server Components and Next.js: what’s affected and how to update safely.

Security News
Socket CEO Feross Aboukhadijeh joins Software Engineering Daily to discuss modern software supply chain attacks and rising AI-driven security risks.

Security News
GitHub has revoked npm classic tokens for publishing; maintainers must migrate, but OpenJS warns OIDC trusted publishing still has risky gaps for critical projects.