Multi-Chain Integration
This document describes the multi-chain architecture of the SN106 validator system, covering how the system integrates with multiple blockchain networks and manages data collection across different DeFi protocols. The system currently supports Solana with planned support for Ethereum and Base networks.
For information about the overall validator engine orchestration, see Validator Engine. For details about weight submission mechanisms, see Weight Submission System.
Architecture Overview
Section titled “Architecture Overview”The SN106 validator implements a flexible multi-chain architecture that allows data collection from multiple blockchain networks while maintaining a unified reward calculation system. The architecture supports both active chains (Solana) and planned chains (Ethereum, Base) through a configurable chain filtering system.
Multi-Chain System Design
Section titled “Multi-Chain System Design”graph TB
subgraph "Configuration Layer"
ENV_CONFIG["ENV.ENABLED_CHAINS"]
CHAIN_CONFIG["CONFIG.getEnabledChains()"]
CHAIN_FILTER["CONFIG.isChainEnabled()"]
end
subgraph "Chain Implementations"
SOLANA_IMPL["Solana Implementation"]
ETH_IMPL["Ethereum Implementation"]
BASE_IMPL["Base Implementation"]
end
subgraph "Protocol Integrations"
RAYDIUM["Raydium CLMM"]
UNISWAP_ETH["Uniswap V3 (Ethereum)"]
UNISWAP_BASE["Uniswap V3 (Base)"]
end
subgraph "Data Collection"
NFT_POSITIONS["NFT Position Data"]
TICK_DATA["Current Tick Data"]
POOL_STATE["Pool State Information"]
end
subgraph "Unified Processing"
DATA_AGGREGATION["Data Aggregation"]
EMISSIONS_CALC["Emissions Calculation"]
WEIGHT_SUBMISSION["Weight Submission"]
end
ENV_CONFIG --> CHAIN_CONFIG
CHAIN_CONFIG --> CHAIN_FILTER
CHAIN_FILTER --> SOLANA_IMPL
CHAIN_FILTER --> ETH_IMPL
CHAIN_FILTER --> BASE_IMPL
SOLANA_IMPL --> RAYDIUM
ETH_IMPL --> UNISWAP_ETH
BASE_IMPL --> UNISWAP_BASE
RAYDIUM --> NFT_POSITIONS
UNISWAP_ETH --> NFT_POSITIONS
UNISWAP_BASE --> NFT_POSITIONS
RAYDIUM --> TICK_DATA
UNISWAP_ETH --> TICK_DATA
UNISWAP_BASE --> TICK_DATA
NFT_POSITIONS --> DATA_AGGREGATION
TICK_DATA --> DATA_AGGREGATION
POOL_STATE --> DATA_AGGREGATION
DATA_AGGREGATION --> EMISSIONS_CALC
EMISSIONS_CALC --> WEIGHT_SUBMISSION
Sources: config/environment.ts:87-96 , README.md:156-159
Chain Configuration System
Section titled “Chain Configuration System”The multi-chain configuration system is centralized in the environment configuration module, providing type-safe access to chain-specific settings and a unified interface for managing multiple blockchain networks.
Configuration Structure
Section titled “Configuration Structure”graph TD
subgraph "Environment Variables"
ENABLED_CHAINS_ENV["ENABLED_CHAINS='SOLANA,ETHEREUM,BASE'"]
SOLANA_ENV["SOLANA_RPC_ENDPOINT"]
ETH_ENV["ETHEREUM_RPC_URL"]
BASE_ENV["BASE_RPC_URL"]
end
subgraph "Type System"
SUPPORTED_CHAIN["type SupportedChain = 'solana'"]
CONFIG_TYPE["CONFIG object with typed chains"]
end
subgraph "Chain-Specific Configs"
SOLANA_CONFIG["CONFIG.SOLANA"]
ETH_CONFIG["CONFIG.ETHEREUM"]
BASE_CONFIG["CONFIG.BASE"]
end
subgraph "Chain Properties"
SOL_PROPS["RPC_ENDPOINT, PROGRAM_ID, CLMM_PROGRAM_ID"]
ETH_PROPS["RPC_URL, SN106_CONTRACT_ADDRESS, UNISWAP_V3_*"]
BASE_PROPS["RPC_URL, SN106_CONTRACT_ADDRESS, UNISWAP_V3_*"]
end
ENABLED_CHAINS_ENV --> SUPPORTED_CHAIN
SOLANA_ENV --> SOLANA_CONFIG
ETH_ENV --> ETH_CONFIG
BASE_ENV --> BASE_CONFIG
SOLANA_CONFIG --> SOL_PROPS
ETH_CONFIG --> ETH_PROPS
BASE_CONFIG --> BASE_PROPS
CONFIG_TYPE --> SOLANA_CONFIG
CONFIG_TYPE --> ETH_CONFIG
CONFIG_TYPE --> BASE_CONFIG
The configuration system provides individual chain configurations with protocol-specific parameters:
| Chain | Protocol | Configuration Properties |
|---|---|---|
| Solana | Raydium CLMM | RPC_ENDPOINT, PROGRAM_ID, CLMM_PROGRAM_ID |
| Ethereum | Uniswap V3 | RPC_URL, SN106_CONTRACT_ADDRESS, UNISWAP_V3_FACTORY_ADDRESS, UNISWAP_V3_POSITION_MANAGER_ADDRESS, MULTICALL_ADDRESS |
| Base | Uniswap V3 | RPC_URL, SN106_CONTRACT_ADDRESS, UNISWAP_V3_FACTORY_ADDRESS, UNISWAP_V3_POSITION_MANAGER_ADDRESS, MULTICALL_ADDRESS |
Sources: config/environment.ts:20-42 , config/environment.ts:99-122
Chain Filtering and Selection
Section titled “Chain Filtering and Selection”The system implements a dynamic chain filtering mechanism that allows validators to operate on specific blockchain networks while maintaining compatibility with the full multi-chain architecture.
Chain Selection Logic
Section titled “Chain Selection Logic”graph TD
subgraph "Chain Selection Process"
ENV_VAR["ENV.ENABLED_CHAINS"]
PARSE_CHAINS["chainsEnv.toUpperCase().split(',')"]
ALL_CHAINS["allChains: ['solana']"]
FILTER_LOGIC["return allChains"]
end
subgraph "Functions"
GET_ENABLED["CONFIG.getEnabledChains()"]
IS_ENABLED["CONFIG.isChainEnabled(chain)"]
VALIDATION["validateEnvironment()"]
end
subgraph "Usage Examples"
VALIDATOR_CHECK["if (CONFIG.isChainEnabled('solana'))"]
CHAIN_LOOP["for (const chain of CONFIG.getEnabledChains())"]
end
ENV_VAR --> PARSE_CHAINS
PARSE_CHAINS --> ALL_CHAINS
ALL_CHAINS --> FILTER_LOGIC
FILTER_LOGIC --> GET_ENABLED
GET_ENABLED --> IS_ENABLED
IS_ENABLED --> VALIDATOR_CHECK
GET_ENABLED --> CHAIN_LOOP
VALIDATION --> ENV_VAR
The current implementation only returns Solana as an enabled chain, with Ethereum and Base support planned for future releases. The getEnabledChains() function in config/environment.ts:87-92 implements this logic by filtering against available chain implementations.
Sources: config/environment.ts:87-96 , config/environment.ts:72
Protocol-Specific Integrations
Section titled “Protocol-Specific Integrations”Each blockchain network integrates with different DeFi protocols for concentrated liquidity provision. The system abstracts these protocol differences through a unified data collection interface.
Protocol Integration Mapping
Section titled “Protocol Integration Mapping”graph LR
subgraph "Solana Integration"
SOLANA_CHAIN["Solana Mainnet"]
RAYDIUM_PROTOCOL["Raydium CLMM Protocol"]
SOL_PROGRAM["SN106_SVM_PROGRAM_ID"]
CLMM_PROGRAM["RAYDIUM_CLMM_PROGRAM_ID"]
end
subgraph "Ethereum Integration"
ETH_CHAIN["Ethereum Mainnet"]
UNISWAP_V3_ETH["Uniswap V3 Protocol"]
ETH_CONTRACT["SN106_CONTRACT_ADDRESS"]
UNI_FACTORY_ETH["UNISWAP_V3_FACTORY_ADDRESS"]
UNI_MANAGER_ETH["UNISWAP_V3_POSITION_MANAGER_ADDRESS"]
end
subgraph "Base Integration"
BASE_CHAIN["Base Network"]
UNISWAP_V3_BASE["Uniswap V3 Protocol"]
BASE_CONTRACT["BASE_SN106_CONTRACT_ADDRESS"]
UNI_FACTORY_BASE["BASE_UNISWAP_V3_FACTORY_ADDRESS"]
UNI_MANAGER_BASE["BASE_UNISWAP_V3_POSITION_MANAGER_ADDRESS"]
end
SOLANA_CHAIN --> RAYDIUM_PROTOCOL
RAYDIUM_PROTOCOL --> SOL_PROGRAM
RAYDIUM_PROTOCOL --> CLMM_PROGRAM
ETH_CHAIN --> UNISWAP_V3_ETH
UNISWAP_V3_ETH --> ETH_CONTRACT
UNISWAP_V3_ETH --> UNI_FACTORY_ETH
UNISWAP_V3_ETH --> UNI_MANAGER_ETH
BASE_CHAIN --> UNISWAP_V3_BASE
UNISWAP_V3_BASE --> BASE_CONTRACT
UNISWAP_V3_BASE --> UNI_FACTORY_BASE
UNISWAP_V3_BASE --> UNI_MANAGER_BASE
Each protocol requires specific contract addresses and program IDs configured through environment variables. The system uses different data fetching strategies:
- Solana/Raydium: Direct program account fetching and CLMM pool state reading
- Ethereum/Base/Uniswap V3: Multicall-optimized contract interaction for position and pool data
Sources: config/environment.ts:26-42 , README.md:156-159
Data Unification Strategy
Section titled “Data Unification Strategy”The multi-chain architecture implements a unified data model that normalizes position and tick data from different protocols into a common format for emissions calculation.
Data Flow Integration
Section titled “Data Flow Integration”graph TD
subgraph "Chain-Specific Data Collection"
SOL_POSITIONS["fetchSolanaPositions()"]
ETH_POSITIONS["fetchEthereumPositions()"]
BASE_POSITIONS["fetchBasePositions()"]
SOL_TICKS["fetchSolanaTicks()"]
ETH_TICKS["fetchEthereumTicks()"]
BASE_TICKS["fetchBaseTicks()"]
end
subgraph "Data Normalization"
UNIFIED_POSITIONS["NFTPosition[]"]
UNIFIED_TICKS["PoolTickData{}"]
CHAIN_PREFIXES["Chain-specific pool identifiers"]
end
subgraph "Unified Processing"
POOL_WEIGHTS["calculatePoolWeights()"]
NFT_EMISSIONS["calculateNFTEmissions()"]
WEIGHT_AGGREGATION["aggregateMinerWeights()"]
end
SOL_POSITIONS --> UNIFIED_POSITIONS
ETH_POSITIONS --> UNIFIED_POSITIONS
BASE_POSITIONS --> UNIFIED_POSITIONS
SOL_TICKS --> UNIFIED_TICKS
ETH_TICKS --> UNIFIED_TICKS
BASE_TICKS --> UNIFIED_TICKS
UNIFIED_POSITIONS --> CHAIN_PREFIXES
UNIFIED_TICKS --> CHAIN_PREFIXES
CHAIN_PREFIXES --> POOL_WEIGHTS
UNIFIED_POSITIONS --> NFT_EMISSIONS
UNIFIED_TICKS --> NFT_EMISSIONS
POOL_WEIGHTS --> WEIGHT_AGGREGATION
NFT_EMISSIONS --> WEIGHT_AGGREGATION
The data unification strategy ensures that position NFTs and tick data from different chains can be processed through the same emissions calculation algorithms while maintaining chain-specific pool identification through prefixed pool identifiers.
Sources: docs/ARCHITECTURE.md:222-267 , docs/ARCHITECTURE.md:493-531
Environment Configuration Interface
Section titled “Environment Configuration Interface”The system exposes a comprehensive configuration interface that provides type-safe access to multi-chain settings and validation mechanisms.
Configuration API Structure
Section titled “Configuration API Structure”graph TD
subgraph "ENV Object (Raw Environment)"
ENV_ENABLED["ENV.ENABLED_CHAINS"]
ENV_SOLANA["ENV.SOLANA_RPC_ENDPOINT"]
ENV_ETH["ENV.ETHEREUM_RPC_URL"]
ENV_BASE["ENV.BASE_RPC_URL"]
end
subgraph "CONFIG Object (Validated)"
CONFIG_CHAINS["CONFIG.getEnabledChains()"]
CONFIG_CHECK["CONFIG.isChainEnabled()"]
CONFIG_SOL["CONFIG.SOLANA"]
CONFIG_ETH["CONFIG.ETHEREUM"]
CONFIG_BASE["CONFIG.BASE"]
end
subgraph "Validation Functions"
VALIDATE_ENV["validateEnvironment()"]
REQUIRED_CHECK["required.filter()"]
MISSING_WARN["console.warn()"]
end
ENV_ENABLED --> CONFIG_CHAINS
ENV_SOLANA --> CONFIG_SOL
ENV_ETH --> CONFIG_ETH
ENV_BASE --> CONFIG_BASE
CONFIG_CHAINS --> CONFIG_CHECK
VALIDATE_ENV --> REQUIRED_CHECK
REQUIRED_CHECK --> MISSING_WARN
CONFIG_SOL --> VALIDATE_ENV
CONFIG_ETH --> VALIDATE_ENV
CONFIG_BASE --> VALIDATE_ENV
The configuration system provides several key interfaces:
CONFIG.getEnabledChains(): Returns array of enabled chains based on environment configurationCONFIG.isChainEnabled(chain): Checks if a specific chain is enabledvalidateEnvironment(): Validates required environment variables and warns about missing values- Chain-specific configuration objects with typed properties for each protocol
Sources: config/environment.ts:154-166 , config/environment.ts:77-149
Network-Specific Features
Section titled “Network-Specific Features”Each blockchain network implementation includes network-specific optimizations and features tailored to the characteristics of the underlying protocol and infrastructure.
Performance Optimization by Chain
Section titled “Performance Optimization by Chain”| Feature | Solana | Ethereum | Base |
|---|---|---|---|
| RPC Optimization | Direct account fetching | Multicall batching | Multicall batching |
| Connection Pooling | WebSocket support | HTTP connection reuse | HTTP connection reuse |
| Batch Processing | Account batch loading | Contract call batching | Contract call batching |
| Error Handling | Solana-specific error codes | EVM revert handling | EVM revert handling |
| Rate Limiting | Solana RPC limits | Ethereum node limits | Base node limits |
The system implements chain-specific timeouts, retry logic, and batch sizes optimized for each network’s characteristics through the performance configuration in config/environment.ts:57-68 .
Sources: config/environment.ts:57-68 , README.md:77-80 , docs/ARCHITECTURE.md:664-683
Extensibility Design
Section titled “Extensibility Design”The multi-chain architecture is designed for easy extension to support additional blockchain networks and DeFi protocols through a standardized integration pattern.
Extension Framework
Section titled “Extension Framework”graph TD
subgraph "Integration Requirements"
NEW_CHAIN["New Chain Integration"]
CHAIN_CONFIG["Add to ENABLED_CHAINS"]
ENV_VARS["Environment Variables"]
TYPE_DEF["Update SupportedChain type"]
end
subgraph "Implementation Pattern"
DATA_FETCH["Implement data fetching"]
TICK_FETCH["Implement tick data fetching"]
ERROR_HANDLE["Chain-specific error handling"]
BATCH_OPT["Optimize batch processing"]
end
subgraph "Validation Steps"
CONFIG_VAL["Add to validateEnvironment()"]
CHAIN_CHECK["Update isChainEnabled()"]
INTEGRATION_TEST["Integration testing"]
end
NEW_CHAIN --> CHAIN_CONFIG
NEW_CHAIN --> ENV_VARS
NEW_CHAIN --> TYPE_DEF
CHAIN_CONFIG --> DATA_FETCH
ENV_VARS --> TICK_FETCH
TYPE_DEF --> ERROR_HANDLE
DATA_FETCH --> BATCH_OPT
TICK_FETCH --> CONFIG_VAL
ERROR_HANDLE --> CHAIN_CHECK
CONFIG_VAL --> INTEGRATION_TEST
CHAIN_CHECK --> INTEGRATION_TEST
BATCH_OPT --> INTEGRATION_TEST
To add a new chain, developers must:
- Add the chain identifier to the
SupportedChaintype in config/environment.ts:72 - Add chain-specific environment variables and configuration objects
- Update the
getEnabledChains()function to include the new chain - Implement chain-specific data fetching functions following the established pattern
- Add validation requirements to
validateEnvironment()function
Sources: config/environment.ts:72 , config/environment.ts:87-96 , config/environment.ts:154-166