Skip to content

Commit

Permalink
refactor: move NFT collections provider to separate file
Browse files Browse the repository at this point in the history
  • Loading branch information
IkigaiLabsETH committed Dec 20, 2024
1 parent 174d296 commit 4d8c4bb
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 52 deletions.
54 changes: 2 additions & 52 deletions packages/plugin-nft-collections/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
import {
Plugin,
Action,
Provider,
IAgentRuntime,
Memory,
State,
ServiceType,
Evaluator,
} from "@ai16z/eliza";
import axios from "axios";

interface NFTCollection {
name: string;
totalSupply: number;
floorPrice: number;
volume24h: number;
}
import { nftCollectionProvider } from "./providers/nft-collections";

interface NFTKnowledge {
mentionsCollection: boolean;
Expand Down Expand Up @@ -96,25 +88,6 @@ function extractNFTDetails(text: string): {
};
}

const fetchNFTCollections = async (): Promise<NFTCollection[]> => {
const API_KEY = process.env.RESERVOIR_API_KEY;
const response = await axios.get(
"https://api.reservoir.tools/collections/v6",
{
headers: {
accept: "application/json",
"x-api-key": API_KEY,
},
}
);
return response.data.collections.map((collection: any) => ({
name: collection.name,
totalSupply: collection.totalSupply,
floorPrice: collection.floorAsk.price.amount.native,
volume24h: collection.volume["1day"],
}));
};

const sweepFloorNFTAction: Action = {
name: "SWEEP_FLOOR_NFT",
similes: ["BUY_FLOOR_NFT", "PURCHASE_FLOOR_NFT"],
Expand Down Expand Up @@ -192,13 +165,7 @@ const nftCollectionAction: Action = {
},
handler: async (runtime: IAgentRuntime, message: Memory) => {
try {
const collections = await fetchNFTCollections();
const response = collections
.map(
(c) =>
`${c.name}: Supply: ${c.totalSupply}, Floor: ${c.floorPrice.toFixed(2)} ETH, 24h Volume: ${c.volume24h.toFixed(2)} ETH`
)
.join("\n");
const response = await nftCollectionProvider.get(runtime, message);
await runtime.sendMessage(message.roomId, response);
return true;
} catch (error) {
Expand Down Expand Up @@ -229,23 +196,6 @@ const nftCollectionAction: Action = {
],
};

const nftCollectionProvider: Provider = {
get: async (runtime: IAgentRuntime, message: Memory, state?: State) => {
try {
const collections = await fetchNFTCollections();
return `Current top NFT collections on Ethereum:\n${collections
.map(
(c) =>
`${c.name}: Supply: ${c.totalSupply}, Floor: ${c.floorPrice.toFixed(2)} ETH, 24h Volume: ${c.volume24h.toFixed(2)} ETH`
)
.join("\n")}`;
} catch (error) {
console.error("Error in NFT collection provider:", error);
return "Unable to fetch NFT collection data at the moment.";
}
},
};

const nftCollectionPlugin: Plugin = {
name: "nft-collection-plugin",
description:
Expand Down
85 changes: 85 additions & 0 deletions packages/plugin-nft-collections/src/providers/nft-collections.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { Provider, IAgentRuntime, Memory, State } from "@ai16z/eliza";
import axios from "axios";

interface NFTCollection {
name: string;
totalSupply: number;
floorPrice: number;
volume24h: number;
}

const CACHE_TTL = 3600000; // 1 hour
let cachedCollections: NFTCollection[] | null = null;
let lastFetchTime = 0;

async function fetchWithRetry(
url: string,
options: any,
retries = 3
): Promise<any> {
try {
return await axios.get(url, options);
} catch (error) {
if (retries > 0) {
await new Promise((resolve) => setTimeout(resolve, 1000));
return fetchWithRetry(url, options, retries - 1);
}
throw error;
}
}

function sanitizeCollection(collection: any): NFTCollection {
return {
name: String(collection.name).slice(0, 100),
totalSupply: Math.max(0, parseInt(collection.totalSupply) || 0),
floorPrice: Math.max(
0,
parseFloat(collection.floorAsk?.price?.amount?.native) || 0
),
volume24h: Math.max(0, parseFloat(collection.volume?.["1day"]) || 0),
};
}

async function fetchCollectionsWithCache(): Promise<NFTCollection[]> {
const now = Date.now();
if (!cachedCollections || now - lastFetchTime > CACHE_TTL) {
const response = await fetchWithRetry(
"https://api.reservoir.tools/collections/v6",
{
headers: {
accept: "application/json",
"x-api-key": process.env.RESERVOIR_API_KEY,
},
}
);

cachedCollections = response.data.collections.map(sanitizeCollection);
lastFetchTime = now;
}
return cachedCollections;
}

function processCollections(collections: NFTCollection[]): string {
return collections
.sort((a, b) => b.volume24h - a.volume24h)
.slice(0, 10)
.map(
(collection) =>
`${collection.name}: Supply: ${collection.totalSupply}, Floor: ${collection.floorPrice.toFixed(
2
)} ETH, 24h Volume: ${collection.volume24h.toFixed(2)} ETH`
)
.join("\n");
}

export const nftCollectionProvider: Provider = {
get: async (runtime: IAgentRuntime, message: Memory, state?: State) => {
try {
const collections = await fetchCollectionsWithCache();
return `Current top NFT collections on Ethereum:\n${processCollections(collections)}`;
} catch (error) {
console.error("Error fetching NFT collections:", error);
return "Unable to fetch NFT collection data at the moment.";
}
},
};

0 comments on commit 4d8c4bb

Please sign in to comment.