The Data Module is your central hub for fetching, processing, and managing on-chain and off-chain data related to Solana assets. It provides seamless integration with multiple data sources including Helius, Birdeye, and CoinGecko.

Core Functionalities

Token Data

Fetch token metadata, balances, prices, and historical price data from multiple sources

NFT & Portfolio Assets

Retrieve user portfolio assets including NFTs and compressed NFTs (cNFTs)

Market Information

Access comprehensive market data from CoinGecko including OHLC and market details

Transaction History

Fetch and process user swap transaction history with enriched metadata

Installation & Setup

1

Environment Variables

Configure your API keys in .env.local:

HELIUS_API_KEY=your_helius_api_key
BIRDEYE_API_KEY=your_birdeye_api_key
COINGECKO_API_KEY=your_coingecko_api_key
2

Import Module

Import the hooks and services you need:

import { 
  useFetchTokens, 
  useTokenDetails, 
  useCoingecko 
} from '@/modules/data-module';
3

Start Fetching

Use the hooks in your components to fetch data

Module Architecture

src/modules/data-module/
├── services/               # Core API integration logic
├── hooks/                  # React hooks for UI integration
├── types/                  # TypeScript definitions
├── utils/                  # Helper functions
└── index.ts               # Public API exports

Core Services

tokenService.ts - Core token data operations

// Key functions available
fetchTokenBalance(walletPublicKey, tokenInfo)
fetchTokenPrice(tokenInfo) 
ensureCompleteTokenInfo(token)
estimateTokenUsdValue(amount, decimals, mint, symbol)
fetchTokenList(params)
searchTokens(params)

Essential Hooks

useFetchTokens()

Fetches all fungible tokens in a user’s wallet with portfolio data.

import { useFetchTokens } from '@/modules/data-module';

function UserTokenList() {
  const { tokens, loading, error, refetch } = useFetchTokens(walletAddress);
  
  if (loading) return <Text>Loading tokens...</Text>;
  if (error) return <Text>Error: {error}</Text>;
  
  return (
    <FlatList
      data={tokens}
      renderItem={({ item }) => (
        <TokenItem token={item} />
      )}
      onRefresh={refetch}
    />
  );
}

Returns:

  • tokens - Array of user’s tokens
  • loading - Loading state
  • error - Error message if any
  • refetch - Function to refresh data

useTokenDetails()

Comprehensive token information for detail views.

import { useTokenDetails } from '@/modules/data-module';

function TokenDetailScreen({ tokenAddress }) {
  const { 
    priceHistory, 
    metadata, 
    tokenOverview, 
    loading,
    selectedTimeframe,
    handleTimeframeChange 
  } = useTokenDetails({ 
    tokenAddress, 
    visible: true 
  });
  
  return (
    <View>
      <TokenChart data={priceHistory} />
      <TokenInfo metadata={metadata} />
      <TokenOverview data={tokenOverview} />
    </View>
  );
}

Parameters:

  • tokenAddress - Token mint address
  • visible - Whether to actively fetch data

Returns:

  • priceHistory - Historical price data
  • metadata - Token metadata
  • tokenOverview - Overview information
  • loading - Loading states
  • selectedTimeframe - Current timeframe
  • handleTimeframeChange - Timeframe selector

useCoingecko()

Access CoinGecko market data with caching.

import { useCoingecko } from '@/modules/data-module';

function MarketDataComponent() {
  const { 
    coinList, 
    searchCoins, 
    searchResults, 
    fetchCoinData,
    loadingCoinList 
  } = useCoingecko();
  
  const handleSearch = (query) => {
    searchCoins(query);
  };
  
  return (
    <View>
      <SearchInput onSearch={handleSearch} />
      <CoinList data={searchResults} />
    </View>
  );
}

useTokenSearch()

Debounced token search with pagination.

import { useTokenSearch } from '@/modules/data-module';

function TokenSearchComponent() {
  const { 
    tokens, 
    loading, 
    searchQuery, 
    setSearchQuery, 
    loadMore,
    refresh 
  } = useTokenSearch('', 300); // 300ms debounce
  
  return (
    <View>
      <TextInput 
        value={searchQuery}
        onChangeText={setSearchQuery}
        placeholder="Search tokens..."
      />
      <FlatList
        data={tokens}
        onEndReached={loadMore}
        onRefresh={refresh}
        renderItem={({ item }) => <TokenSearchResult token={item} />}
      />
    </View>
  );
}

Quick Start Example

import { useFetchTokens, TokenInfo } from '@/modules/data-module';
import { useWallet } from '@/modules/wallet-providers';

function UserTokenPortfolio() {
  const { wallet } = useWallet();
  const { tokens, loading, error, refetch } = useFetchTokens(wallet?.address);

  if (loading) return <LoadingSpinner />;
  if (error) return <ErrorMessage message={error} />;

  return (
    <View>
      <Button title="Refresh Portfolio" onPress={refetch} />
      <FlatList
        data={tokens}
        keyExtractor={(item: TokenInfo) => item.address}
        renderItem={({ item }) => (
          <View style={styles.tokenItem}>
            <Image source={{ uri: item.logoURI }} style={styles.tokenLogo} />
            <View>
              <Text style={styles.tokenName}>{item.name}</Text>
              <Text style={styles.tokenSymbol}>{item.symbol}</Text>
            </View>
            <Text style={styles.tokenBalance}>{item.balance}</Text>
          </View>
        )}
      />
    </View>
  );
}

Utility Functions

token_utilities
object
fetch_utilities
object
display_formatters
object

Data Sources Integration

Helius

Primary Use: RPC calls, transaction history, asset fetching

  • Enhanced Solana RPC
  • Transaction parsing
  • Asset metadata

Birdeye

Primary Use: Token prices, security analysis, market data

  • Real-time prices
  • Security scoring
  • Trade data
  • Price history

CoinGecko

Primary Use: Market information, coin listings

  • Coin directories
  • Market cap data
  • OHLC data
  • Global statistics

Advanced Usage Patterns

Custom Data Fetching

import { tokenService } from '@/modules/data-module';

// Custom token price fetching with fallback
async function getTokenPriceWithFallback(tokenInfo) {
  try {
    // Try Birdeye first
    const price = await tokenService.fetchTokenPrice(tokenInfo);
    return price;
  } catch (error) {
    // Fallback to Jupiter
    return await fetchJupiterPrice(tokenInfo.address);
  }
}

Batch Data Operations

import { coingeckoService } from '@/modules/data-module';

// Fetch multiple coin data efficiently
async function fetchPortfolioMarketData(tokenAddresses) {
  const coinIds = await mapAddressesToCoinIds(tokenAddresses);
  const marketData = await coingeckoService.getBatchCoinMarkets(coinIds);
  return marketData;
}

Real-time Price Updates

function useRealTimeTokenPrice(tokenAddress) {
  const [price, setPrice] = useState(null);
  
  useEffect(() => {
    const interval = setInterval(async () => {
      const newPrice = await tokenService.fetchTokenPrice({ address: tokenAddress });
      setPrice(newPrice);
    }, 10000); // Update every 10 seconds
    
    return () => clearInterval(interval);
  }, [tokenAddress]);
  
  return price;
}

Error Handling

API Rate Limits: Be mindful of rate limits when making frequent requests. The module includes retry logic but respect provider limits.

function TokenDataWithErrorHandling() {
  const { tokens, loading, error } = useFetchTokens(walletAddress);
  
  if (error) {
    // Handle different error types
    if (error.includes('rate limit')) {
      return <RateLimitError onRetry={refetch} />;
    }
    if (error.includes('network')) {
      return <NetworkError onRetry={refetch} />;
    }
    return <GenericError message={error} />;
  }
  
  return <TokenList tokens={tokens} loading={loading} />;
}

Performance Optimization

Caching: The module implements intelligent caching for CoinGecko data and token metadata to reduce API calls.

// Use debounced search to avoid excessive API calls
const { tokens, setSearchQuery } = useTokenSearch('', 500); // 500ms debounce

// Implement virtual scrolling for large token lists
<VirtualizedList
  data={tokens}
  getItem={(data, index) => data[index]}
  getItemCount={(data) => data.length}
  renderItem={({ item }) => <TokenItem token={item} />}
/>

Integration with Other Modules

With Wallet Providers

import { useWallet } from '@/modules/wallet-providers';
import { useFetchTokens } from '@/modules/data-module';

function ConnectedTokenList() {
  const { wallet } = useWallet();
  const { tokens } = useFetchTokens(wallet?.address);
  
  return <TokenPortfolio tokens={tokens} />;
}

With Swap Module

import { useSwap } from '@/modules/swap';
import { useTokenSearch } from '@/modules/data-module';

function TokenSwapInterface() {
  const { executeSwap } = useSwap();
  const { tokens, setSearchQuery } = useTokenSearch();
  
  return (
    <SwapCard 
      availableTokens={tokens}
      onTokenSearch={setSearchQuery}
      onSwap={executeSwap}
    />
  );
}

Troubleshooting

common_issues
object

API Reference

For detailed API documentation, see:


The Data Module serves as the foundation for all blockchain data needs in your Solana application, providing reliable, cached, and efficiently formatted data from multiple sources.