Core Integration Guide - Solana
This guide shows how to integrate Alien Solana SSO verification and authentication into any JavaScript/TypeScript project using the core SDK.
Requirements
- A modern web browser with JavaScript enabled
- localStorage and sessionStorage support
@solana/web3.js^1.95.0 or higher- A registered provider from the dev portal with provider address
Installation
npm install @alien_org/solana-sso-sdk-core @solana/web3.jsSetup
Initialize the Client
import { AlienSolanaSsoClient } from '@alien_org/solana-sso-sdk-core';
const client = new AlienSolanaSsoClient({
ssoBaseUrl: 'https://sso.alien-api.com',
providerAddress: 'your-provider-address'
});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 (Solana Attestation Service) program IDcredentialAuthority(optional): Credential authority public keycredentialName(optional): Credential nameschemaName(optional): Schema nameschemaVersion(optional): Schema version
Authentication Flow
Step 1: Connect Wallet
First, ensure the user has connected their Solana wallet:
import { Connection, PublicKey } from '@solana/web3.js';
// Get user's wallet public key (from wallet adapter or similar)
const userPublicKey = new PublicKey('user-wallet-address');
const solanaAddress = userPublicKey.toBase58();Step 2: Check for Existing Attestation
Before initiating the attestation creation flow, check if the wallet already has an attestation:
const sessionAddress = await client.getAttestation(solanaAddress);
if (sessionAddress) {
console.log('User is already authenticated! Session:', sessionAddress);
// User is authenticated, proceed to app
return;
}
// No attestation found, proceed with creation flow
console.log('No attestation found, starting attestation creation...');Step 3: Generate Deep Link (If No Attestation)
const { deep_link, polling_code, expired_at } = await client.generateDeeplink(solanaAddress);
// Display QR code with deep_link
displayQRCode(deep_link);
// Or redirect mobile users
window.location.href = deep_link;The generateDeeplink() method takes the user’s Solana wallet address and returns:
deep_link: Link for QR code or mobile redirectpolling_code: Code for polling authentication statusexpired_at: Unix timestamp when polling code expires
Step 4: Poll for Authorization
let pollResponse;
const pollInterval = setInterval(async () => {
pollResponse = await client.pollAuth(polling_code);
if (pollResponse.status === 'authorized') {
clearInterval(pollInterval);
// Proceed to transaction building
console.log('Authorized! Session address:', pollResponse.session_address);
} else if (pollResponse.status === 'rejected') {
clearInterval(pollInterval);
console.error('User rejected authentication');
} else if (pollResponse.status === 'expired') {
clearInterval(pollInterval);
console.error('Authentication expired');
}
// If status is 'pending', continue polling
}, 5000);When status is 'authorized', the response includes:
session_address: Session identifieroracle_signature: Signature bytes for verificationoracle_public_key: Oracle public keytimestamp: Unix timestampexpiry: Expiry timestamptransaction: Pre-built transaction (optional)
Step 5: Build Attestation Transaction
import { Connection, Transaction, sendAndConfirmTransaction } from '@solana/web3.js';
// Create Solana connection
const connection = new Connection('https://api.mainnet-beta.solana.com');
// Build attestation transaction
const transaction = await client.buildCreateAttestationTransaction({
connection,
payerPublicKey: userPublicKey,
sessionAddress: pollResponse.session_address!,
oracleSignature: new Uint8Array(pollResponse.oracle_signature!),
oraclePublicKey: new PublicKey(pollResponse.oracle_public_key!),
timestamp: pollResponse.timestamp!,
expiry: pollResponse.expiry!,
});Step 6: Sign and Send Transaction
// Sign transaction with user's wallet
// (Implementation depends on your wallet integration)
const signedTransaction = await wallet.signTransaction(transaction);
// Send and confirm transaction
const signature = await sendAndConfirmTransaction(
connection,
signedTransaction,
[/* signers if needed */]
);
console.log('Attestation created! Signature:', signature);Step 7: Verify Attestation
After the transaction is confirmed, verify the on-chain attestation:
const sessionAddress = await client.getAttestation(solanaAddress);
if (sessionAddress) {
console.log('Attestation created successfully! Session:', sessionAddress);
} else {
console.log('Attestation not found, please try again');
}Complete Example
import { AlienSolanaSsoClient } from '@alien_org/solana-sso-sdk-core';
import { Connection, PublicKey, Transaction, sendAndConfirmTransaction } from '@solana/web3.js';
const client = new AlienSolanaSsoClient({
ssoBaseUrl: 'https://sso.alien-api.com',
providerAddress: 'your-provider-address',
});
const connection = new Connection('https://api.mainnet-beta.solana.com');
async function authenticateUser(userWallet: any) {
try {
const userPublicKey = userWallet.publicKey;
const solanaAddress = userPublicKey.toBase58();
// Check if already authenticated
const existingSession = await client.getAttestation(solanaAddress);
if (existingSession) {
console.log('Already authenticated:', existingSession);
return;
}
// Generate deep link
const { deep_link, polling_code } = await client.generateDeeplink(solanaAddress);
// Display QR code
displayQRCode(deep_link);
// Poll for authorization
const pollInterval = setInterval(async () => {
const response = await client.pollAuth(polling_code);
if (response.status === 'authorized') {
clearInterval(pollInterval);
// Build attestation transaction
const transaction = await client.buildCreateAttestationTransaction({
connection,
payerPublicKey: userPublicKey,
sessionAddress: response.session_address!,
oracleSignature: new Uint8Array(response.oracle_signature!),
oraclePublicKey: new PublicKey(response.oracle_public_key!),
timestamp: response.timestamp!,
expiry: response.expiry!,
});
// Sign transaction
const signedTransaction = await userWallet.signTransaction(transaction);
// Send transaction
const signature = await sendAndConfirmTransaction(
connection,
signedTransaction,
[]
);
console.log('Attestation created! Signature:', signature);
// Verify attestation
const sessionAddress = await client.getAttestation(solanaAddress);
console.log('Verified session:', sessionAddress);
hideQRCode();
} else if (response.status === 'rejected' || response.status === 'expired') {
clearInterval(pollInterval);
console.error('Authentication failed:', response.status);
hideQRCode();
}
}, 5000);
} catch (error) {
console.error('Authentication error:', error);
}
}
function displayQRCode(deepLink: string) {
// Implementation to display QR code
}
function hideQRCode() {
// Implementation to hide QR code
}PDA Derivation Utilities
The SDK provides utility functions for deriving Program Derived Addresses (PDAs):
import {
deriveProgramStatePda,
deriveCredentialSignerPda,
deriveSessionRegistryPda,
deriveSessionEntryPda,
deriveSolanaEntryPda,
deriveAttestationPda,
deriveCredentialPda,
deriveSchemaPda,
} from '@alien_org/solana-sso-sdk-core';
// Example: Derive attestation PDA
const [attestationPda, bump] = deriveAttestationPda(
credentialAddress,
schemaAddress,
userPublicKey,
sasProgramId
);Error Handling
try {
const { deep_link, polling_code } = await client.generateDeeplink(solanaAddress);
} catch (error) {
console.error('Failed to generate deep link:', error);
// Handle network error or server error
}
try {
const transaction = await client.buildCreateAttestationTransaction({
connection,
payerPublicKey: userPublicKey,
sessionAddress: pollResponse.session_address!,
oracleSignature: new Uint8Array(pollResponse.oracle_signature!),
oraclePublicKey: new PublicKey(pollResponse.oracle_public_key!),
timestamp: pollResponse.timestamp!,
expiry: pollResponse.expiry!,
});
} catch (error) {
console.error('Transaction building failed:', error);
// Could be due to missing program state or invalid parameters
}Solana Programs
The SDK interacts with three on-chain programs:
Credential Signer Program
ID: 9cstDz8WWRAFaq1vVpTjfHz6tjgh6SJaqYFeZWi1pFHG
Manages credential signing and verification.
Session Registry Program
ID: DeHa6pyZ2CFSbQQiNMm7FgoCXqmkX6tXG77C4Qycpta6
Stores session entries and maps Solana addresses to sessions.
SAS (Solana Attestation Service)
ID: 22zoJMtdu4tQc2PzL74ZUT7FrwgB1Udec8DdW4yw4BdG
Creates and manages on-chain attestations.
Next Steps
- API Reference - Core - Complete API documentation for Core SDK.
- React Integration Guide - For React applications.
- Demo App - Example implementation and source code.