React Integration Guide - Solana
This guide shows how to integrate Alien Solana SSO into React applications using the React SDK with Solana wallet adapters.
Requirements
- React 19.1.1 or higher
- React DOM 19.1.1 or higher
@solana/web3.js^1.95.0 or higher@solana/wallet-adapter-react^0.15.0 or higher- A modern web browser with JavaScript enabled
- localStorage and sessionStorage support
- A registered provider from the dev portal, with provider address
Installation
npm install @alien_org/solana-sso-sdk-react @solana/web3.js @solana/wallet-adapter-reactThe React SDK requires Solana wallet adapter packages as peer dependencies.
Setup
Alien Solana SSO Provider
Wrap your app with both wallet adapter providers and AlienSolanaSsoProvider:
import { AlienSolanaSsoProvider } from '@alien_org/solana-sso-sdk-react';
function App() {
return (
<WalletContextProvider>
<AlienSolanaSsoProvider
config={{
ssoBaseUrl: 'https://sso.alien-api.com',
providerAddress: 'your-provider-address'
}}
>
<YourApp />
</AlienSolanaSsoProvider>
</WalletContextProvider>
);
}
export default App;Configuration Options
ssoBaseUrl(required): Base URL of the SSO serviceproviderAddress(required): Your provider address from dev portalpollingInterval(optional): Polling interval in milliseconds (default: 5000)credentialSignerProgramId(optional): Credential Signer program IDsessionRegistryProgramId(optional): Session Registry program IDsasProgramId(optional): SAS program ID
Using the useSolanaAuth Hook
The useSolanaAuth() hook provides access to Solana authentication state and methods.
import { useSolanaAuth } from '@alien_org/solana-sso-sdk-react';
function Dashboard() {
const { auth, wallet, logout } = useSolanaAuth();
if (!auth.sessionAddress) {
return <div>Not authenticated</div>;
}
return (
<div>
<p>Wallet: {wallet.publicKey?.toBase58()}</p>
<p>Session: {auth.sessionAddress}</p>
<button onClick={logout}>Logout</button>
</div>
);
}Auth State
The auth object contains:
{
sessionAddress: string | null;
}Available Properties and Methods
const {
client, // Direct access to AlienSolanaSsoClient instance
auth, // Authentication state
wallet, // Solana wallet adapter
connectionAdapter, // Solana connection from context
queryClient, // React Query client instance
generateDeeplink, // Generate authentication deep link
pollAuth, // Poll for authentication status
verifyAttestation, // Verify on-chain attestation
logout, // Clear authentication state
openModal, // Open built-in Solana sign-in modal
closeModal, // Close sign-in modal
isModalOpen // Modal open state
} = useSolanaAuth();Using Pre-built Components
SolanaSignInButton
A pre-styled button that opens the Solana sign-in modal.
import { SolanaSignInButton } from '@alien_org/solana-sso-sdk-react';
import { useWallet } from '@solana/wallet-adapter-react';
import { WalletMultiButton } from '@solana/wallet-adapter-react-ui';
function LoginPage() {
const { connected } = useWallet();
if (!connected) {
return (
<div>
<h1>Connect Your Wallet</h1>
<WalletMultiButton />
</div>
);
}
return (
<div>
<h1>Sign In with Alien</h1>
<SolanaSignInButton />
</div>
);
}SolanaSignInModal
The modal is automatically rendered by AlienSolanaSsoProvider and handles:
- QR code display
- Polling for authentication
- Transaction building and signing
- On-chain attestation creation
Control it via the useSolanaAuth() hook:
import { useSolanaAuth } from '@alien_org/solana-sso-sdk-react';
function CustomButton() {
const { openModal } = useSolanaAuth();
return <button onClick={openModal}>Sign In</button>;
}Complete Example
import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react';
import { WalletModalProvider, WalletMultiButton } from '@solana/wallet-adapter-react-ui';
import { AlienSolanaSsoProvider, useSolanaAuth, SolanaSignInButton } from '@alien_org/solana-sso-sdk-react';
import { useWallet } from '@solana/wallet-adapter-react';
import { clusterApiUrl } from '@solana/web3.js';
import { useMemo } from 'react';
import '@solana/wallet-adapter-react-ui/styles.css';
function App() {
const endpoint = useMemo(() => clusterApiUrl('mainnet-beta'), []);
return (
<ConnectionProvider endpoint={endpoint}>
<WalletProvider wallets={[]} autoConnect>
<WalletModalProvider>
<AlienSolanaSsoProvider
config={{
ssoBaseUrl: 'https://sso.alien-api.com',
providerAddress: 'your-provider-address',
}}
>
<Dashboard />
</AlienSolanaSsoProvider>
</WalletModalProvider>
</WalletProvider>
</ConnectionProvider>
);
}
function Dashboard() {
const { connected } = useWallet();
const { auth, logout } = useSolanaAuth();
if (!connected) {
return (
<div>
<h1>Connect Wallet</h1>
<WalletMultiButton />
</div>
);
}
if (!auth.sessionAddress) {
return (
<div>
<h1>Sign In</h1>
<SolanaSignInButton />
</div>
);
}
return (
<div>
<h1>Dashboard</h1>
<p>Session: {auth.sessionAddress}</p>
<button onClick={logout}>Logout</button>
</div>
);
}
export default App;Custom Authentication Flow
If you want to implement a custom UI:
import { useSolanaAuth } from '@alien_org/solana-sso-sdk-react';
import { useWallet } from '@solana/wallet-adapter-react';
import { useState, useEffect } from 'react';
import QRCode from 'react-qr-code';
function CustomAuth() {
const { wallet, generateDeeplink, pollAuth } = useSolanaAuth();
const [deepLink, setDeepLink] = useState<string | null>(null);
const [pollingCode, setPollingCode] = useState<string | null>(null);
const handleSignIn = async () => {
if (!wallet.publicKey) return;
const response = await generateDeeplink(wallet.publicKey.toBase58());
setDeepLink(response.deep_link);
setPollingCode(response.polling_code);
};
useEffect(() => {
if (!pollingCode) return;
const interval = setInterval(async () => {
const response = await pollAuth(pollingCode);
if (response.status === 'authorized') {
clearInterval(interval);
// The provider will automatically handle transaction creation and signing
setDeepLink(null);
setPollingCode(null);
} else if (response.status === 'rejected' || response.status === 'expired') {
clearInterval(interval);
alert(`Authentication ${response.status}`);
setDeepLink(null);
setPollingCode(null);
}
}, 5000);
return () => clearInterval(interval);
}, [pollingCode, pollAuth]);
if (deepLink) {
return (
<div>
<h2>Scan QR Code</h2>
<QRCode value={deepLink} />
</div>
);
}
return <button onClick={handleSignIn}>Sign In with Alien</button>;
}Protected Routes
Create a protected route component:
import { useSolanaAuth } from '@alien_org/solana-sso-sdk-react';
import { useWallet } from '@solana/wallet-adapter-react';
import { Navigate } from 'react-router-dom';
function ProtectedRoute({ children }: { children: React.ReactNode }) {
const { connected } = useWallet();
const { auth } = useSolanaAuth();
if (!connected) {
return <Navigate to="/connect-wallet" />;
}
if (!auth.sessionAddress) {
return <Navigate to="/sign-in" />;
}
return <>{children}</>;
}
// Usage
<Route
path="/dashboard"
element={
<ProtectedRoute>
<Dashboard />
</ProtectedRoute>
}
/>Grace Period Mechanism
The Solana provider implements a 60-second grace period after attestation creation to handle RPC indexing delays:
// After successful attestation creation
// Session address is cached for 60 seconds
// verifyAttestation() returns cached value immediately
// Background verification runs after grace period expiresStorage keys:
alien-sso_solana_authed_address- Authenticated Solana addressalien-sso_session_address- Session addressalien-sso_attestation_created_at- Timestamp of attestation creation
Verifying Attestation on Mount
import { useSolanaAuth } from '@alien_org/solana-sso-sdk-react';
import { useWallet } from '@solana/wallet-adapter-react';
import { useEffect, useState } from 'react';
function App() {
const { wallet } = useWallet();
const { verifyAttestation, auth } = useSolanaAuth();
const [isVerifying, setIsVerifying] = useState(true);
useEffect(() => {
const verify = async () => {
if (wallet.publicKey) {
await verifyAttestation(wallet.publicKey.toBase58());
}
setIsVerifying(false);
};
verify();
}, [wallet.publicKey]);
if (isVerifying) {
return <div>Verifying authentication...</div>;
}
return auth.sessionAddress ? <Dashboard /> : <LoginPage />;
}TypeScript Support
The React SDK is fully typed:
import type { SolanaAuthState, AlienSolanaSsoClient } from '@alien_org/solana-sso-sdk-react';
const auth: SolanaAuthState = useSolanaAuth().auth;
const client: AlienSolanaSsoClient = useSolanaAuth().client;Next Steps
- API Reference - React - Complete API documentation for React SDK.
- Demo App - Example implementation and source code.
- Core Integration Guide - For vanilla JavaScript/TypeScript projects.