Skip to content

Configuration & Setup for Solana Adapters

1. Environment Configuration

Required Environment Variables

# Solana RPC Endpoints
RPC_URL_SOLANA=https://api.mainnet-beta.solana.com
# or use premium providers:
# RPC_URL_SOLANA=https://solana-mainnet.g.alchemy.com/v2/YOUR-API-KEY
# RPC_URL_SOLANA=https://rpc.helius.xyz/?api-key=YOUR-API-KEY
 
# API Configuration
ABSINTHE_API_URL=https://adapters.absinthe.network
ABSINTHE_API_KEY=your-absinthe-api-key
 
# Solana-specific Configuration
ABS_CONFIG='{"balanceFlushIntervalHours":48,"type":"spl-transfers","name":"spl-transfers","toBlock":0,"contractAddress":"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA","chainId":1000,"fromBlock":331145334}'
 
# Price Data (if needed)
COINGECKO_API_KEY=your-coingecko-api-key
 
# Database Configuration (if required by adapter)
DB_URL=postgresql://username:password@localhost:5432/database
REDIS_URL="redis://localhost:6379"

2. Setup Instructions

Prerequisites

  • Node.js (v20+)
  • pnpm package manager
  • PostgreSQL database (if required by adapter)
  • API keys for required services
  • Solana RPC endpoint access

Installation Steps

1. Clone and Install

git clone https://github.com/AbsintheLabs/absinthe-adapters.git
cd absinthe-adapters
pnpm install

2. Environment Setup

cp .env.example .env
# Edit .env with your Solana configuration

3. Solana Configuration Setup

ABS_CONFIG='{"balanceFlushIntervalHours":48,"type":"spl-transfers","name":"spl-transfers","toBlock":0,"contractAddress":"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA","chainId":1000,"fromBlock":331145334}'

What is ABS_CONFIG for Solana Adapters?

  • ABS_CONFIG is a single environment variable that holds your Solana protocol configuration as a minified JSON string.
  • For Solana adapters, this config controls which programs, instructions, and tokens your adapter will track.
  • It uses the same validation pattern as EVM adapters but with Solana-specific fields.

How to Use It

A. Generate Your Config

1. Start with the Config Template
{
  "balanceFlushIntervalHours": 6,
  "type": "spl-transfers",
  "name": "usdc-transfers",
  "contractAddress": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
  "chainId": 1000,
  "fromBlock": 150000000,
  "toBlock": 0
}
2. Customize for Your Use Case
  • contractAddress: The Solana program ID you want to track (e.g., SPL Token program)
  • fromBlock: The slot number to start indexing from
  • chainId: Always 1000 for Solana mainnet
  • balanceFlushIntervalHours: How often to flush balance data to API
3. Minify the JSON
cat config.json | jq -c

B. Set in Your Environment

ABS_CONFIG='{"balanceFlushIntervalHours":6,"type":"spl-transfers","name":"usdc-transfers","toBlock":0,"contractAddress":"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA","chainId":1000,"fromBlock":150000000}'

How the Code Uses It

On startup, the code checks for ABS_CONFIG in your environment:

  • If present, it parses and validates it using the Zod schema
  • If not present, it loads config.json from the project directory
  • If neither is available, it throws an error
Relevant code snippet:
if (envResult.data.ABS_CONFIG) {
  configData = JSON.parse(envResult.data.ABS_CONFIG);
} else {
  // fallback to config.json
  configData = JSON.parse(fs.readFileSync(configFilePath, 'utf8'));
}
Schema Validation:
const splTransfersProtocolSchema = z.object({
  type: z.literal('spl-transfers'),
  name: z.string(),
  contractAddress: z.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/, 'Must be valid Solana program ID'),
  chainId: z.literal(1000),
  fromBlock: z.number(),
  toBlock: z.number(),
  trackedTokens: z.record(z.string(), z.number()),
});

Validation ensures:

  • contractAddress is a valid Solana program ID
  • chainId is 1000 (Solana mainnet) [Just for this project]
  • fromBlock and toBlock are valid slot numbers
  • Required fields exist and are correctly typed
Chain Metadata Enrichment:
const chainConfig = {
  chainArch: ChainType.SOLANA,
  networkId: 1000,
  chainShortName: 'SOL',
  chainName: 'Solana',
};

4. Database Setup (if required)

# For local development
docker-compose up -d postgres

5. Run typegen

npx @subsquid/solana-typegen src/abi TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA

where TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA is your program ID.

6. Run Development

pnpm dev

3. Solana-Specific Configuration

Tracked Tokens Configuration

const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
const USDC_DECIMALS = 6;
 
const TRACKED_TOKENS = {
  [USDC_MINT]: USDC_DECIMALS,
};

Program IDs

// SPL Token Program
const TOKEN_PROGRAM_ID = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA';
 
// Other common programs
const TOKEN_2022_PROGRAM_ID = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb';
const ASSOCIATED_TOKEN_PROGRAM_ID = 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL';

API Integration

1. Absinthe API Client

Client Configuration

const apiClient = new AbsintheApiClient({
  baseUrl: env.baseConfig.absintheApiUrl,
  apiKey: env.baseConfig.absintheApiKey,
  minTime: 90, // Rate limiting
});

Data Transmission

// Send transaction events
await apiClient.send(transactions);
 
// Send time-weighted balance events
await apiClient.send(balances);

2. Rate Limiting & Retry Logic

Solana RPC Configuration

const rpcClient = new SolanaRpcClient({
  url: process.env.RPC_URL_SOLANA,
  rateLimit: 100, // requests per second
});

Error Handling

try {
  await apiClient.send(data);
} catch (error) {
  console.error('API transmission failed:', error);
  // Automatic retry with exponential backoff
}

4. Solana-Specific Best Practices

Slot vs Block Numbers

  • Solana uses "slots" instead of "blocks"
  • Configure fromBlock with the slot number you want to start from
  • Use Solana explorers to find specific slot numbers

RPC Endpoint Selection

  • Use dedicated Solana RPC providers for better performance
  • Consider rate limits when choosing RPC endpoints
  • Helius, QuickNode, and Alchemy offer Solana RPC services

Token Account Tracking

  • Solana token balances are tracked per token account
  • Each wallet can have multiple token accounts for the same mint
  • Use transactionTokenBalances to track balance changes

Why Use This Pattern for Solana?

  • Portability: Same config-driven approach as EVM adapters
  • Program Flexibility: Easy to switch between different Solana programs
  • Slot Range Control: Precise control over which slots to process
  • Token Tracking: Built-in support for SPL token balance changes
  • Validation: Schema ensures your Solana config is correct