DEV Community

Danilo Jamaal
Danilo Jamaal

Posted on

Build an AI Crypto Research Agent with Claude and LunarCrush API

⏱️ 20 min read | πŸ“Š Beginner-Intermediate | πŸ› οΈ React + Vite + Python + Claude API + LunarCrush API

TL;DR: Build a full-stack agent using Anthropic's Claude API to automatically fetch, analyze, and report on Ethereum's Galaxy Score and social sentiment from the LunarCrush API, providing real-time insights for informed trading decisions.

  • Build time: 25 minutes
  • Lines of code: ~150 lines
  • Key API: /topic/{topic}/v1
  • ROI potential: $500-$2000/month with 20-50 users providing alerts or trading signals.

Table of Contents

  1. The Untapped Power of Social Intelligence in Crypto
  2. Prerequisites
  3. Project Structure
  4. Step 1: Setting Up the React + Vite Frontend
  5. Step 2: Creating the Backend API (Express)
  6. Step 3: Fetching and Displaying Data in the Frontend
  7. Step 4: Integrating Claude AI Analysis
  8. Step 5: Displaying Claude's Analysis in the Frontend
  9. Testing It Out
  10. Troubleshooting
  11. How This Compares
  12. ROI & First Customer Playbook
  13. Extend This With AI
  14. FAQ
  15. Glossary
  16. What's Next

The Untapped Power of Social Intelligence in Crypto

Most crypto traders rely solely on price charts and technical indicators. But what if you could anticipate market movements by understanding the collective sentiment and social buzz surrounding a cryptocurrency before it impacts the price? Ignoring social intelligence data is like navigating a ship with only a compass, ignoring the weather reports and ocean currents.

This is where LunarCrush comes in. Its API provides a wealth of social and market data, including the Galaxy Score, which offers a holistic view of a cryptocurrency's social engagement. However, constantly monitoring this data manually is time-consuming.

That's why we're building an automated crypto research agent using Anthropic's Claude API and Python. This agent will:

  1. Fetch Ethereum's Galaxy Score and social sentiment from the LunarCrush API.
  2. Use Claude's AI capabilities to analyze the data for significant changes.
  3. Generate a concise report summarizing the findings.

This automated agent can be invaluable for:

  • Traders: Identify potential buying or selling opportunities based on social signals.
  • Researchers: Track the evolving social narrative around Ethereum.
  • Developers: Build sophisticated trading algorithms powered by social intelligence.

This project bridges the gap between raw data and actionable insights, giving you a competitive edge in the volatile crypto market.

πŸ“– What is Galaxy Score?
Galaxy Score (0-100) measures social engagement strength by combining mentions,
interactions, sentiment, and contributor diversity. Scores above 70 often
correlate with increased market activity. Learn more

Prerequisites

Before we start, make sure you have the following:

  • Node.js 18+: Required for running the Vite development server.
  • LunarCrush API key: You'll need an API key to access LunarCrush data. Get one here - use code JAMAALBUILDS for 15% off.
  • Basic React + Vite knowledge: Familiarity with React components and the Vite build tool is helpful.
  • Python 3.7+: For the Claude AI agent.
  • Anthropic API Key: You'll need an Anthropic API key to use Claude.

Project Structure

Here's the final project structure we'll build:

crypto-research-agent/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ App.tsx
β”‚   β”œβ”€β”€ App.css
β”‚   └── main.tsx
β”œβ”€β”€ server/
β”‚   β”œβ”€β”€ index.js
β”‚   β”œβ”€β”€ claude_agent.py
β”‚   └── .env
β”œβ”€β”€ package.json
β”œβ”€β”€ vite.config.ts
└── .env.local
Enter fullscreen mode Exit fullscreen mode

Step 1: Setting Up the React + Vite Frontend

First, let's create a new React project using Vite:

npm create vite@latest crypto-research-agent --template react-ts
cd crypto-research-agent
npm install
Enter fullscreen mode Exit fullscreen mode

This will scaffold a basic React application with TypeScript support. Now, let's install the necessary dependencies for making API calls and displaying data:

npm install axios
Enter fullscreen mode Exit fullscreen mode

We'll use axios to fetch data from our backend API.

Explanation:

This step sets the foundation for our user interface. We're using Vite because it's a fast and efficient build tool that makes development a breeze. axios is a popular HTTP client that simplifies making API requests from our React components. By using TypeScript, we can add type safety to our code, reducing the risk of errors. This initial setup ensures that we have a solid base to build upon in the following steps. Common pitfalls include forgetting to install dependencies or using an outdated version of Node.js.

Pro Tip: Consider using a UI library like Material UI or Ant Design to quickly create a visually appealing interface.

After running these commands, you should see a basic React application running at http://localhost:5173/.

Step 2: Creating the Backend API (Express)

Now, let's create a backend API using Express to fetch data from LunarCrush and interact with Claude. Create a new directory named server in the root of your project and navigate into it:

mkdir server
cd server
npm init -y
npm install express cors dotenv axios
Enter fullscreen mode Exit fullscreen mode

Create a file named index.js in the server directory and add the following code:

const express = require('express');
const cors = require('cors');
const axios = require('axios');
require('dotenv').config();

const app = express();
const port = 3000;

app.use(cors());
app.use(express.json());

app.get('/api/ethereum', async (req, res) => {
  try {
    const response = await axios.get(
      `https://lunarcrush.com/api4/public/topic/ethereum/v1`,
      {
        headers: {
          Authorization: `Bearer ${process.env.LUNARCRUSH_API_KEY}`,
        },
      }
    );
    res.json(response.data);
  } catch (error) {
    console.error('Error fetching Ethereum data:', error);
    res.status(500).json({ error: 'Failed to fetch Ethereum data' });
  }
});

app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Create a .env file in the server directory and add your LunarCrush API key:

LUNARCRUSH_API_KEY=YOUR_LUNARCRUSH_API_KEY
Enter fullscreen mode Exit fullscreen mode

Add this line to your main project package.json to run the server concurrently with vite:

  "concurrently": "concurrently \"npm run dev\" \"cd server && node index.js\""
Enter fullscreen mode Exit fullscreen mode

Now, add the following to the scripts section of your main package.json file:

  "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "start": "npm run build && npm run preview",
    "server": "cd server && node index.js",
    "concurrently": "concurrently \"npm run dev\" \"cd server && node index.js\""
Enter fullscreen mode Exit fullscreen mode

Run both servers with:

npm run concurrently
Enter fullscreen mode Exit fullscreen mode

Explanation:

This step creates a simple Express server that acts as a proxy between our React frontend and the LunarCrush API. We're using cors to enable cross-origin requests, allowing our frontend to access the backend API. The /api/ethereum endpoint fetches data from the LunarCrush API using your API key. We're storing the API key in a .env file for security reasons. Handling errors gracefully is crucial, so we're catching any errors that occur during the API call and returning an error response to the client.

Pro Tip: Implement caching on the backend to reduce the number of requests to the LunarCrush API and improve performance.

After running these commands, you should see the Express server running at http://localhost:3000. Visiting http://localhost:3000/api/ethereum in your browser should return the Ethereum data from the LunarCrush API.

Step 3: Fetching and Displaying Data in the Frontend

Now, let's modify the React frontend to fetch data from our backend API and display it. Open src/App.tsx and replace the existing code with the following:

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import './App.css';

interface EthereumData {
  galaxy_score: string;
  alt_rank: string;
  sentiment: string;
  social_mentions_24h: string;
  social_contributors: string;
  price: string;
  price_change_24h: string;
  market_cap: string;
  volume_24h: string;
}

function App() {
  const [ethereumData, setEthereumData] = useState<EthereumData | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get('http://localhost:3000/api/ethereum');
        setEthereumData(response.data.data);
        setLoading(false);
      } catch (err: any) {
        setError(err.message);
        setLoading(false);
      }
    };

    fetchData();
  }, []);

  if (loading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error}</div>;
  }

  return (
    <div className="App">
      <h1>Ethereum Social Intelligence</h1>
      {ethereumData && (
        <div>
          <p>Galaxy Score: {ethereumData.galaxy_score}</p>
          <p>Alt Rank: {ethereumData.alt_rank}</p>
          <p>Sentiment: {ethereumData.sentiment}</p>
          <p>Social Mentions (24h): {ethereumData.social_mentions_24h}</p>
          <p>Social Contributors: {ethereumData.social_contributors}</p>
          <p>Price: {ethereumData.price}</p>
           <p>Price Change (24h): {ethereumData.price_change_24h}</p>
          <p>Market Cap: {ethereumData.market_cap}</p>
          <p>Volume (24h): {ethereumData.volume_24h}</p>
        </div>
      )}
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Explanation:

This step integrates the frontend with our backend API. We're using the useState hook to manage the Ethereum data, loading state, and error state. The useEffect hook fetches data from the backend API when the component mounts. We're displaying a loading message while the data is being fetched and an error message if something goes wrong. Once the data is fetched successfully, we display it in the component.

Pro Tip: Use a more sophisticated loading indicator, such as a spinner or progress bar, to improve the user experience. Also, implement proper error handling and display user-friendly error messages.

After saving the changes, you should see the Ethereum data from the LunarCrush API displayed in your React application.

Step 4: Integrating Claude AI Analysis

Now comes the exciting part: integrating Anthropic's Claude API to analyze the data. This requires setting up a Python script that interacts with Claude and the LunarCrush data.

First, install the Anthropic Python client:

pip install anthropic
Enter fullscreen mode Exit fullscreen mode

Create a new Python file named claude_agent.py in the server directory:

import anthropic
import json
import os
from dotenv import load_dotenv
import asyncio
import aiohttp

load_dotenv()

async def fetch_ethereum_data():
    api_url = "http://localhost:3000/api/ethereum"
    async with aiohttp.ClientSession() as session:
        async with session.get(api_url) as response:
            if response.status == 200:
                return await response.json()
            else:
                print(f"Error fetching data: {response.status}")
                return None

async def analyze_data_with_claude(data):
    if data is None:
        return "Failed to retrieve Ethereum data."

    client = anthropic.AsyncAnthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))

    prompt = f"""You are a crypto market analyst. Analyze the following Ethereum data and provide a concise summary of key insights, focusing on potential trading opportunities based on social sentiment and Galaxy Score.

    Data: {json.dumps(data, indent=2)}

    Your analysis:"""

    try:
        message = await client.messages.create(
            model="claude-3-opus-20240229",
            max_tokens=1024,
            messages=[{"role": "user", "content": prompt}]
        )
        return message.content[0].text
    except Exception as e:
        return f"Error analyzing data with Claude: {str(e)}"

async def main():
    ethereum_data = await fetch_ethereum_data()
    if ethereum_data:
        analysis = await analyze_data_with_claude(ethereum_data)
        print("Claude's Analysis:\n", analysis)

if __name__ == "__main__":
    asyncio.run(main())
Enter fullscreen mode Exit fullscreen mode

Add your Anthropic API key to the .env file in the server directory:

ANTHROPIC_API_KEY=YOUR_ANTHROPIC_API_KEY
Enter fullscreen mode Exit fullscreen mode

Modify the index.js file to execute the Python script and return the analysis to the frontend:

const express = require('express');
const cors = require('cors');
const axios = require('axios');
const { spawn } = require('child_process');
require('dotenv').config();

const app = express();
const port = 3000;

app.use(cors());
app.use(express.json());

app.get('/api/ethereum', async (req, res) => {
  try {
    const response = await axios.get(
      `https://lunarcrush.com/api4/public/topic/ethereum/v1`,
      {
        headers: {
          Authorization: `Bearer ${process.env.LUNARCRUSH_API_KEY}`,
        },
      }
    );
    res.json(response.data);
  } catch (error) {
    console.error('Error fetching Ethereum data:', error);
    res.status(500).json({ error: 'Failed to fetch Ethereum data' });
  }
});

app.get('/api/claude-analysis', async (req, res) => {
  try {
    const pythonProcess = spawn('python', ['./claude_agent.py'], { cwd: __dirname });
    let data = '';

    pythonProcess.stdout.on('data', (chunk) => {
      data += chunk;
    });

    pythonProcess.stderr.on('data', (chunk) => {
      console.error(`stderr: ${chunk}`);
    });

    pythonProcess.on('close', (code) => {
      if (code === 0) {
        // Extract the analysis from the output
        const analysisStart = data.indexOf("Claude's Analysis:\n");
        if (analysisStart !== -1) {
            const analysis = data.substring(analysisStart + "Claude's Analysis:\n".length).trim();
            res.json({ analysis: analysis });
        } else {
            res.status(500).json({ error: 'Analysis not found in output' });
        }
      } else {
        res.status(500).json({ error: `Python script exited with code ${code}` });
      }
    });
  } catch (error) {
    console.error('Error running Claude analysis:', error);
    res.status(500).json({ error: 'Failed to run Claude analysis' });
  }
});

app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Explanation:

This step integrates Claude's analytical capabilities into our workflow. We're using the anthropic Python library to interact with the Claude API. The analyze_data_with_claude function takes the Ethereum data as input and constructs a prompt that instructs Claude to analyze the data and provide a concise summary of key insights. The prompt is crucial for guiding Claude's analysis and ensuring that it focuses on the most relevant aspects of the data. We're using the child_process module in Node.js to execute the Python script from our backend API. This allows us to seamlessly integrate Claude's analysis into our existing infrastructure.

Pro Tip: Experiment with different prompts to fine-tune Claude's analysis and get the most valuable insights. Consider adding more context to the prompt, such as historical data or specific trading strategies.

Step 5: Displaying Claude's Analysis in the Frontend

Finally, let's modify the React frontend to fetch and display Claude's analysis. Open src/App.tsx and add the following code:

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import './App.css';

interface EthereumData {
  galaxy_score: string;
  alt_rank: string;
  sentiment: string;
  social_mentions_24h: string;
  social_contributors: string;
  price: string;
  price_change_24h: string;
  market_cap: string;
  volume_24h: string;
}

function App() {
  const [ethereumData, setEthereumData] = useState<EthereumData | null>(null);
  const [claudeAnalysis, setClaudeAnalysis] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const ethereumResponse = await axios.get('http://localhost:3000/api/ethereum');
        setEthereumData(ethereumResponse.data.data);

        const claudeResponse = await axios.get('http://localhost:3000/api/claude-analysis');
        setClaudeAnalysis(claudeResponse.data.analysis);

        setLoading(false);
      } catch (err: any) {
        setError(err.message);
        setLoading(false);
      }
    };

    fetchData();
  }, []);

  if (loading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error}</div>;
  }

  return (
    <div className="App">
      <h1>Ethereum Social Intelligence</h1>
      {ethereumData && (
        <div>
          <p>Galaxy Score: {ethereumData.galaxy_score}</p>
          <p>Alt Rank: {ethereumData.alt_rank}</p>
          <p>Sentiment: {ethereumData.sentiment}</p>
          <p>Social Mentions (24h): {ethereumData.social_mentions_24h}</p>
          <p>Social Contributors: {ethereumData.social_contributors}</p>
          <p>Price: {ethereumData.price}</p>
          <p>Price Change (24h): {ethereumData.price_change_24h}</p>
          <p>Market Cap: {ethereumData.market_cap}</p>
          <p>Volume (24h): {ethereumData.volume_24h}</p>
        </div>
      )}
      <h2>Claude's Analysis</h2>
      <p>{claudeAnalysis}</p>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Explanation:

This step completes the integration by displaying Claude's analysis in our React application. We're using the useState hook to manage the Claude analysis data. The useEffect hook now fetches both the Ethereum data and Claude's analysis from our backend API. We're displaying Claude's analysis below the Ethereum data.

Pro Tip: Use a more visually appealing format to display Claude's analysis, such as a card or a text box. Consider adding a loading indicator while Claude's analysis is being fetched.

After saving the changes, you should see Claude's analysis displayed in your React application.

Testing It Out

To test the complete system, follow these steps:

  1. Ensure both the React frontend (Vite) and the Express backend are running (npm run concurrently).
  2. Open your browser and navigate to http://localhost:5173/.
  3. You should see the Ethereum data from LunarCrush, followed by Claude's analysis.

Example Output:

You should see the raw data points from the LunarCrush API, followed by Claude's summary of the data. For example, if the Galaxy Score is high and social sentiment is positive, Claude might say something like:

"The Galaxy Score for Ethereum is high, indicating strong social engagement. Combined with positive sentiment, this suggests a potential buying opportunity."

If the Galaxy Score is low and social sentiment is negative, Claude might say:

"The Galaxy Score for Ethereum is low, indicating weak social engagement. Coupled with negative sentiment, this suggests a potential selling opportunity."

Edge Cases:

  • API Errors: Ensure your LunarCrush and Anthropic API keys are valid. Check the console for error messages.
  • Claude Unresponsiveness: Claude might occasionally fail to provide an analysis. Implement retry logic in your backend API to handle this.

Troubleshooting

Error Cause Solution
401 Unauthorized Invalid API key Check your .env file has the correct LunarCrush or Anthropic key
429 Too Many Requests Rate limit exceeded Implement caching (60s minimum), or upgrade with code JAMAALBUILDS
CORS error Browser security policy Use server-side fetch via Express, not direct browser calls
Empty response Topic not found Verify topic name matches LunarCrush catalog (e.g., "ethereum" not "ETH")
TypeError: fetch Node version <18 Update Node.js or install node-fetch package
Python ModuleNotFoundError Missing Python dependency Run pip install anthropic aiohttp python-dotenv
Claude timeout API latency Increase timeout, implement retry logic with exponential backoff

πŸ’‘ Pro tip: Use mock data during development to avoid rate limits and iterate faster.

ROI & First Customer Playbook

This project has significant monetization potential. Here's the math:

πŸ’° Monetization Math:

  • Starter: 50 users Γ— $10/mo = $500 MRR (basic alerts and analysis)
  • Pro: 20 users Γ— $25/mo = $500 MRR (advanced analysis, custom alerts)
  • Enterprise: 5 clients Γ— $200/mo = $1000 MRR (dedicated support, custom integrations)

πŸš€ First Customer Acquisition:

Here's a specific 3-step path to your first paying customer:

  1. Where to find them:
    • r/CryptoCurrency, r/algotrading (Reddit)
    • Crypto Twitter (share insights, not just promotion)
    • LunarCrush Discord, crypto trading communities (Discord)
  2. How to pitch it:
    • "Get real-time Ethereum social intelligence alerts powered by AI."
    • "Stop missing out on market-moving social signals."
    • "Automate your crypto research with Claude's analysis."
  3. What to offer first:
    • 5 free beta spots in exchange for feedback
    • Early-bird pricing (50% off first 10)
    • Use testimonials for the next wave

πŸ“Š Competitive Landscape:

Alternatives include manual data checking and expensive SaaS platforms. Our advantage is the combination of real-time LunarCrush data, AI-powered analysis, and a simple, customizable setup.

πŸ€– Extend This With AI

Paste these prompts into Claude or ChatGPT to add features to your project:

Add Email Alerts:

"Take this LunarCrush + Claude monitoring code and add email alerts using Resend/SendGrid when Galaxy Score > 70 or sentiment drops below 40"

Add Multi-Asset Support:

"Modify this code to track Bitcoin, Ethereum, and Solana simultaneously and display a comparison table of their Galaxy Scores and sentiment"

Add Telegram Bot:

"Convert this Express API into a Telegram bot that responds to /check commands with the latest Ethereum social intelligence analysis"

Add Historical Trends:

"Extend this to fetch 30-day historical data using the LunarCrush time_series endpoint and display trend charts"

❓ FAQ

Q: Can I track multiple assets with this code?
A: Yes! Modify the backend API to fetch data for multiple cryptocurrencies.

Q: Can I use this for stocks, not just crypto?
A: Yes! LunarCrush tracks stocks, crypto, and other topics. Same API structure.

Q: How do I handle API errors gracefully?
A: Implement retry logic with exponential backoff in your backend API.

πŸ“š Glossary

  • Galaxy Score: LunarCrush's proprietary 0-100 metric measuring social engagement strength
  • AltRank: Relative ranking of an asset vs. others based on social + price activity
  • Social Dominance: Percentage of social volume an asset commands vs. total market
  • Sentiment: Aggregate positive/negative analysis from social posts (0-100)
  • Claude API: Anthropic's API for programmatic access to Claude AI models for text analysis and generation

What's Next

Here are some ideas for extending this project:

  1. Alert System: Implement an alert system that sends notifications when the Galaxy Score or social sentiment changes significantly.
  2. Trading Bot Integration: Integrate the agent with a trading bot to automate trading decisions based on social intelligence.
  3. Customizable Analysis: Allow users to customize the prompts used by Claude to tailor the analysis to their specific needs.
  4. Sentiment Analysis: Implement your own sentiment analysis model to compare with LunarCrush's sentiment data.

By combining the power of LunarCrush's social intelligence data with Anthropic's Claude, you can gain a significant edge in the crypto market. Start building today and unlock the potential of automated crypto research!


πŸ“š Resources

πŸš€ Ready to scale? Use code JAMAALBUILDS for 15% off the Builder plan when you need higher rate limits and real-time data for production apps.


πŸ™‹ About the Author

Built something cool with this tutorial? Share it!

#LunarCrushBuilder - Show off what you built!

Top comments (0)