Skip to content

Commit

Permalink
feat: add depin project fetcher
Browse files Browse the repository at this point in the history
  • Loading branch information
nicky-ru committed Dec 19, 2024
1 parent c9c3ddf commit 5d08db1
Show file tree
Hide file tree
Showing 6 changed files with 330 additions and 21 deletions.
206 changes: 206 additions & 0 deletions packages/plugin-depin/src/actions/fetchDepinscanData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import {
elizaLogger,
generateText,
HandlerCallback,
ModelClass,
type IAgentRuntime,
type Memory,
type State,
} from "@ai16z/eliza";

import { DepinDataProvider } from "../providers/depinData";
import { DepinScanMetrics, DepinScanProject } from "../types/depin";

export const fetchDepinscanDataAction = {
name: "DEPINSCAN_DATA",
description: "Fetches metrics and projects data from DePINScan",
handler: async (
runtime: IAgentRuntime,
_message: Memory,
state: State,
_options: any,
callback?: HandlerCallback
) => {
elizaLogger.log("Fetch DePINScan action handler called");

try {
const metrics = await DepinDataProvider.fetchDepinscanMetrics();
const projects = await DepinDataProvider.fetchDepinscanProjects();

const response = await generateText({
runtime,
context: depinAnalysisTemplate(state, metrics, projects),
modelClass: ModelClass.LARGE,
});

if (callback) {
callback({
text: response,
content: {
success: true,
metrics,
projects: JSON.stringify(projects, (key, value) =>
typeof value === "bigint" ? value.toString() : value
),
},
});
}

return true;
} catch (error) {
console.error("Error during DePINScan data fetching:", error);
if (callback) {
callback({
text: `Error fetching DePINScan data: ${error.message}`,
content: { error: error.message },
});
}
return false;
}
},
validate: async (_runtime: IAgentRuntime) => {
return true;
},
examples: [
[
{
user: "user",
content: {
text: "Which DePIN project has the highest market cap?",
},
},
{
user: "assistant",
content: {
text: "The DePIN project with the highest market cap is Solana, with a market cap of $106,247,097,756.01.",
action: "DEPINSCAN_DATA",
},
},
],
[
{
user: "user",
content: {
text: "Show me all projects running on Solana.",
},
},
{
user: "assistant",
content: {
text: "The following projects are running on Solana: Solana and Render.",
action: "DEPINSCAN_DATA",
},
},
],
[
{
user: "user",
content: {
text: "What are the categories of the Render project?",
},
},
{
user: "assistant",
content: {
text: "The Render project belongs to the following categories: Server, AI.",
action: "DEPINSCAN_DATA",
},
},
],
[
{
user: "user",
content: {
text: "Compare the token prices of Solana and Render.",
},
},
{
user: "assistant",
content: {
text: "Solana (SOL) is priced at $221.91, while Render (RNDR) is priced at $9.02.",
action: "DEPINSCAN_DATA",
},
},
],
[
{
user: "user",
content: {
text: "What is the network status of all listed projects?",
},
},
{
user: "assistant",
content: {
text: "Both Solana and Render are currently on the Mainnet.",
action: "DEPINSCAN_DATA",
},
},
],
],
similes: [
"ANALYZE_PROJECTS",
"FILTER_PROJECTS",
"GET_PROJECT_CATEGORIES",
"COMPARE_TOKEN_PRICES",
"GET_NETWORK_STATUS",
],
};

const depinAnalysisTemplate = (
state: State,
metrics: DepinScanMetrics,
projects: DepinScanProject
) =>
`
### 📊 DePIN Analysis Request
#### 🗂️ **State Information**
\`\`\`
${state}
\`\`\`
#### 📈 **Metrics Data**
\`\`\`
${metrics}
\`\`\`
#### 🏗️ **Projects Data**
\`\`\`
${JSON.stringify(projects, (key, value) =>
typeof value === "bigint" ? value.toString() : value
)}
\`\`\`
---
### 📝 **Instructions for the Agent**
Based on the state information, metrics, and project data provided above, perform the analysis requested by the user.
While focusing on the user's specific request, you may optionally include the following types of analysis if relevant:
1. **Top Projects by Market Cap**:
- Identify the projects with the highest market capitalization and list them in descending order.
2. **Token Price Insights**:
- Compare the token prices of different projects and highlight any significant differences.
3. **Network Status Overview**:
- Group the projects based on their network status (e.g., Mainnet, Testnet).
4. **Layer 1 Distribution**:
- Analyze how many projects are deployed on each Layer 1 blockchain.
5. **Categories Breakdown**:
- List the different categories each project belongs to and summarize the focus areas.
6. **Key Insights**:
- Provide high-level observations based on the data, such as trends, notable outliers, or potential opportunities.
---
### 🎯 **Agent’s Objective**
Prioritize delivering the analysis requested by the user. Include additional insights or analysis types from the list above **only if they support or enhance the user’s request**.
`;
3 changes: 2 additions & 1 deletion packages/plugin-depin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import type { Plugin } from "@ai16z/eliza";

import { depinDataProvider } from "./providers/depinData";
import { fetchDepinscanDataAction } from "./actions/fetchDepinscanData";

export const depinPlugin: Plugin = {
name: "depin",
description: "DePIN plugin",
providers: [depinDataProvider],
evaluators: [],
services: [],
actions: [],
actions: [fetchDepinscanDataAction],
};

export default depinPlugin;
25 changes: 22 additions & 3 deletions packages/plugin-depin/src/providers/depinData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import {
elizaLogger,
} from "@ai16z/eliza";

import type { DepinScanMetrics } from "../types/depin";
import type { DepinScanMetrics, DepinScanProject } from "../types/depin";

const DEPIN_METRICS_URL =
export const DEPIN_METRICS_URL =
"https://gateway1.iotex.io/depinscan/explorer?is_latest=true";
export const DEPIN_PROJECTS_URL = "https://metrics-api.w3bstream.com/project";

export class DepinDataProvider {
constructor() {}
Expand All @@ -18,6 +19,10 @@ export class DepinDataProvider {
const res = await fetch(DEPIN_METRICS_URL);
return res.json();
};
static fetchDepinscanProjects = async (): Promise<DepinScanProject> => {
const res = await fetch(DEPIN_PROJECTS_URL);
return res.json();
};
}

export const depinDataProvider: Provider = {
Expand All @@ -29,8 +34,22 @@ export const depinDataProvider: Provider = {
try {
const depinMetricsData =
await DepinDataProvider.fetchDepinscanMetrics();
const depinProjects =
await DepinDataProvider.fetchDepinscanProjects();

return `
#### 📈 **Metrics Data**
\`\`\`
${depinMetricsData}
\`\`\`
return JSON.stringify(depinMetricsData);
#### 🏗️ **Projects Data**
\`\`\`
${JSON.stringify(depinProjects, (key, value) =>
typeof value === "bigint" ? value.toString() : value
)}
\`\`\`
`;
} catch (error) {
elizaLogger.error("Error in DePIN data provider:", error);
return null;
Expand Down
43 changes: 26 additions & 17 deletions packages/plugin-depin/src/test/depinData.test.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import { describe, expect, it, vi } from "vitest";

import { DepinDataProvider } from "../providers/depinData";

const METRICS_OBJECT = [
{
date: "2024-12-17",
total_projects: "291",
market_cap: "36046044620.57570635160",
total_device: "19416950",
},
];
import {
DEPIN_METRICS_URL,
DEPIN_PROJECTS_URL,
DepinDataProvider,
} from "../providers/depinData";
import { mockDepinscanMetrics, mockDepinscanProjects } from "./mockData";

vi.stubGlobal(
"fetch",
vi.fn(() =>
Promise.resolve({
json: () => Promise.resolve(METRICS_OBJECT),
})
)
vi.fn((url) => {
if (url.includes(DEPIN_METRICS_URL)) {
return Promise.resolve({
json: () => Promise.resolve(mockDepinscanMetrics),
});
} else if (url.includes(DEPIN_PROJECTS_URL)) {
return Promise.resolve({
json: () => Promise.resolve(mockDepinscanProjects),
});
} else {
return Promise.reject(new Error("Unknown endpoint"));
}
})
);

describe("Depin Data provider", () => {
Expand All @@ -26,9 +30,14 @@ describe("Depin Data provider", () => {

expect(ddp).toBeDefined();
});
it("should fetch depin metrics", async () => {
it("should fetch depinscan metrics", async () => {
const metrics = await DepinDataProvider.fetchDepinscanMetrics();

expect(metrics).toEqual(METRICS_OBJECT);
expect(metrics).toEqual(mockDepinscanMetrics);
});
it("should fetch depinscan projects", async () => {
const projects = await DepinDataProvider.fetchDepinscanProjects();

expect(projects).toEqual(mockDepinscanProjects);
});
});
53 changes: 53 additions & 0 deletions packages/plugin-depin/src/test/mockData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
export const mockDepinscanMetrics = [
{
date: "2024-12-17",
total_projects: "291",
market_cap: "36046044620.57570635160",
total_device: "19416950",
},
];

export const mockDepinscanProjects = [
{
project_name: "Solana",
slug: "solana",
logo: "https://depinscan-prod.s3.us-east-1.amazonaws.com/next-s3-uploads/3160a9ec-42df-4f02-9db6-5aadc61323d8/solana.svg",
description:
"Solana is a general purpose layer 1 blockchain that works well for DePIN (decentralized physical infrastructure Network) projects due to its low transaction cost, high-throughput speed, scalability and existing Solana DePIN ecosystem. The most renowned Solana DePIN projects include Helium, Hivemapper and Render.",
trusted_metric: true,
token: "SOL",
layer_1: ["Solana"],
categories: ["Chain"],
market_cap: "106247097756.0147",
token_price: "221.91",
total_devices: 0,
network_status: "Mainnet",
avg_device_cost: "",
days_to_breakeven: "",
estimated_daily_earnings: "",
chainid: "",
coingecko_id: "solana",
fully_diluted_valuation: "131508718985",
},
{
project_name: "Render",
slug: "render",
logo: "https://depinscan-prod.s3.amazonaws.com/depin/9e5f0bb330344d580b9e30d338d6ab6d.png",
description:
"Render is a decentralized rendering platform supporting next-generation media production.",
trusted_metric: true,
token: "RNDR",
layer_1: ["Solana"],
categories: ["Server", "AI"],
market_cap: "4659773671.856073",
token_price: "9.02",
total_devices: 0,
network_status: "Mainnet",
avg_device_cost: "",
days_to_breakeven: "",
estimated_daily_earnings: "",
chainid: "1",
coingecko_id: "render-token",
fully_diluted_valuation: "4705509105",
},
];
Loading

0 comments on commit 5d08db1

Please sign in to comment.