Skip to content

WalletUiAuth

The WalletUiAuth component wraps the headless useWalletUiAuth hook for one wallet. It prefers native solana:signIn and falls back to connected-account solana:signMessage when native SIWS is unavailable.

NameTypeDescription
children(auth: WalletUiAuthState) => JSXRender function for auth state.
walletUiWalletWallet to use for the auth attempt.
NameTypeDescription
canSignInbooleanWhether this wallet can attempt auth.
isSigningInbooleanWhether a sign-in request is in progress.
messageSigningAvailablebooleanWhether the target account supports solana:signMessage.
nativeSignInAvailablebooleanWhether the wallet supports solana:signIn.
reasonWalletUiAuthUnavailableReason | undefinedWhy auth is unavailable for this wallet/account.
signIn(options?: WalletUiAuthSignInOptions) => Promise<WalletUiAuthResult>Starts the native or fallback auth flow for the wallet.

signIn() resolves to:

NameTypeDescription
accountUiWalletAccountAccount that signed in.
inputSolanaSignInInputSIWS input used for native SIWS or fallback message construction.
method'solana:signIn' | 'solana:signMessage'Auth method used.
signedMessageUint8ArrayExact bytes signed by the wallet.
signatureUint8ArrayEd25519 signature returned by the wallet.
import { WalletUiAuth, WalletUiAuthError, useWalletUi } from '@wallet-ui/react';
function AuthButton() {
const { wallet } = useWalletUi();
if (!wallet) {
return <button disabled>Connect wallet</button>;
}
return (
<WalletUiAuth wallet={wallet}>
{({ canSignIn, isSigningIn, reason, signIn }) => {
async function handleClick() {
try {
const result = await signIn({
input: {
domain: window.location.host,
nonce: await fetch('/api/auth/nonce').then(res => res.text()),
statement: 'Sign in to Example App.',
uri: window.location.origin,
version: '1',
},
});
await fetch('/api/auth/verify', {
body: JSON.stringify({
input: result.input,
method: result.method,
signature: Array.from(result.signature),
signedMessage: Array.from(result.signedMessage),
walletAddress: result.account.address,
}),
headers: { 'content-type': 'application/json' },
method: 'POST',
});
} catch (e) {
if (e instanceof WalletUiAuthError) {
console.error(e.reason);
return;
}
throw e;
}
}
return (
<button disabled={!canSignIn || isSigningIn} onClick={handleClick}>
{isSigningIn ? 'Signing in...' : reason ? 'Connect wallet' : 'Sign in'}
</button>
);
}}
</WalletUiAuth>
);
}

If you render your own wallet list, wrap each wallet row with WalletUiAuth. The component can connect that wallet first when no account is connected, then use native SIWS or message signing.

import { WalletUiAuth, useWalletUiWallets } from '@wallet-ui/react';
function WalletAuthList() {
const wallets = useWalletUiWallets();
return wallets.map(wallet => (
<WalletUiAuth key={wallet.name} wallet={wallet}>
{({ isSigningIn, signIn }) => (
<button disabled={isSigningIn} onClick={() => signIn()}>
{wallet.name}
</button>
)}
</WalletUiAuth>
));
}
ReasonMeaning
auth-unsupportedThe wallet has neither native SIWS nor message-signing fallback.
message-signing-unavailableThe wallet reported no output from solana:signMessage.
missing-domainFallback SIWS message construction needs input.domain or location.host.
wallet-not-connectedFallback auth tried to connect the wallet but received no account.

For a complete auth flow, see the Sign In With Solana guide.