Overview
Sovran integrates with Routstr to provide direct access to leading AI models through a pay-per-use model. Chat with GPT-4, Claude, Gemini, and other models by paying with satoshis from your wallet.
Routstr charges per message in sats based on token usage. Typical costs range from less than 1 sat to several sats per message depending on the model and message length.
Available Models
Sovran supports multiple AI providers through Routstr:
OpenAI GPT-4, GPT-3.5 Turbo and other OpenAI models
Anthropic Claude Sonnet, Opus and other Claude models
Google Gemini Pro, Flash and other Google models
xAI Grok and other xAI models
DeepSeek DeepSeek models for code and reasoning
Perplexity Perplexity models with web search
Features
Multi-Session Support
Manage multiple conversations simultaneously:
Session Management : Create, switch between, and delete conversation sessions
Persistent History : All messages are saved locally and synced across sessions
Auto-Titling : Sessions are automatically titled based on your first message
// From stores/routstrStore.ts
interface RoutstrSession {
id : string ;
title : string ;
createdAt : number ;
messages : RoutstrMessage [];
}
Model Selection
Switch between AI models at any time:
Browse available models organized by provider
See pricing information (sats per 1M tokens)
View model capabilities and descriptions
Filter to text-only models or include multimodal
Wallet Integration
Create Wallet
Fund your Routstr wallet by sending a Cashu token
Check Balance
View your balance in sats or msats
Send Messages
Messages are deducted automatically from your balance
Top Up
Add more funds anytime by sending another token
Implementation Details
API Integration
Sovran uses the Routstr API for all AI interactions:
// From helper/routstr/api.ts
const ROUTSTR_BASE_URL = 'https://api.routstr.com/v1' ;
// Wallet operations
export async function checkBalance ( apiKey : string ) : Promise < BalanceResponse >
export async function createWalletFromToken ( cashuToken : string ) : Promise < CreateWalletResponse | null >
export async function topUpBalance ( apiKey : string , cashuToken : string ) : Promise < TopUpResponse >
// Model operations
export async function getModels () : Promise < RoutstrModel []>
export async function sendMessage (
apiKey : string ,
messages : { role : 'user' | 'assistant' | 'system' ; content : string }[],
options : { model ?: string ; temperature ?: number ; max_tokens ?: number ; stream ?: boolean }
)
Streaming Responses
Messages stream token-by-token for a responsive experience:
// SSE stream parsing for React Native
async function* parseSSEStream (
response : Response
) : AsyncGenerator < OpenAI . Chat . Completions . ChatCompletionChunk > {
const reader = body . getReader ();
const decoder = new TextDecoder ( 'utf-8' );
let buffer = '' ;
while ( true ) {
const { done , value } = await reader . read ();
if ( done ) return ;
buffer += decoder . decode ( value , { stream: true });
const lines = buffer . split ( ' \n ' );
buffer = lines . pop () || '' ;
for ( const line of lines ) {
if ( line . startsWith ( 'data: ' )) {
const data = line . slice ( 6 ). trim ();
if ( data === '[DONE]' ) return ;
yield JSON . parse ( data );
}
}
}
}
Model Pricing
Each model includes pricing information in sats:
interface RoutstrModel {
id : string ;
name : string ;
description : string ;
sats_pricing : {
prompt : number ; // Sats per 1M input tokens
completion : number ; // Sats per 1M output tokens
request : number ; // Sats per request
max_cost : number ; // Maximum cost per request
};
architecture : {
input_modalities : string []; // ['text', 'image', etc.]
output_modalities : string []; // ['text', etc.]
};
}
State Management
Conversation state is managed with Zustand and persisted locally:
// From stores/routstrStore.ts
interface RoutstrState {
apiKey : string | null ; // Cashu token or persistent wallet key
balance : number | null ; // Balance in msats
conversationHistory : RoutstrMessage [];
selectedModel : string | null ;
sessions : RoutstrSession [];
currentSessionId : string | null ;
modelsCache : ModelsCache | null ; // 5 minute TTL
}
UI Components
Sessions Panel
Slide-out panel for managing conversations:
// From components/blocks/routstr/SessionsPanel.tsx
interface SessionsPanelProps {
isOpen : boolean ;
onClose : () => void ;
onSessionSelect ?: ( sessionId : string ) => void ;
onNewSession ?: () => void ;
onRefreshBalance ?: () => void ;
onTopUp ?: () => void ;
onSwitchModel ?: () => void ;
}
Features:
Animated slide-in from left (300ms duration)
Gesture-based closing (swipe left to dismiss)
User profile with avatar and balance
Current model indicator
Session list with timestamps
Model Cards
Visual cards showing available AI models:
// From app/(drawer)/(tabs)/explore/index.tsx
const AIModelCard = ({ model } : { model : RoutstrModel }) => {
const { provider , modelName } = extractModelName ( model );
const icon = getProviderIcon ( provider );
const gradient = getProviderGradient ( provider );
return (
< TouchableOpacity >
< LinearGradient colors = { gradient } >
< Icon name = { icon } />
< Text > { modelName } </ Text >
< Text > { provider } </ Text >
< Badge > { model . sats_pricing . prompt } sats/1M tokens </ Badge >
</ LinearGradient >
</ TouchableOpacity >
);
};
Error Handling
Routstr errors are caught and displayed with user-friendly messages:
const FRIENDLY_MESSAGES : Record < number , string > = {
401 : 'Authentication failed. Please check your API key.' ,
402 : 'Insufficient balance. Please top up your account.' ,
429 : 'Rate limit exceeded. Please wait a moment before trying again.' ,
502 : 'Service temporarily unavailable. Please try again in a few minutes.' ,
503 : 'Service temporarily unavailable. Please try again in a few minutes.' ,
504 : 'Request timeout. The service is taking too long to respond.' ,
};
Best Practices
Cost vs Quality : More expensive models like GPT-4 provide better responses but cost more sats
Context Length : Choose models with longer context windows for complex conversations
Modality : Select text-only models for chat, multimodal for image analysis
Keep Balance : Maintain enough sats for several messages
Top Up Regularly : Add funds before running out to avoid interruptions
Monitor Costs : Check pricing before sending long messages
Topic-Based : Create separate sessions for different topics
Clean Up : Delete old sessions to keep your list organized
Descriptive Titles : First message becomes the title, so make it descriptive
Code Reference
Source Files
app/(drawer)/(tabs)/explore/index.tsx:17-444 - Model browsing and selection UI
components/blocks/routstr/SessionsPanel.tsx:1-512 - Session management panel
stores/routstrStore.ts:1-341 - State management and persistence
helper/routstr/api.ts:1-422 - API client and streaming
Key Functions
getModels() - Fetch available AI models
sendMessage() - Send chat message with streaming
createWalletFromToken() - Create Routstr wallet from Cashu token
checkBalance() - Check current wallet balance
topUpBalance() - Add funds to wallet