forked from elizaOS/eliza
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ce18601
commit d53e365
Showing
7 changed files
with
335 additions
and
250 deletions.
There are no files selected for viewing
52 changes: 52 additions & 0 deletions
52
packages/plugin-nft-collections/src/actions/get-collections.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { Action, IAgentRuntime, Memory } from "@ai16z/eliza"; | ||
import { nftCollectionProvider } from "../providers/nft-collections"; | ||
|
||
export const getCollectionsAction: Action = { | ||
name: "GET_NFT_COLLECTIONS", | ||
similes: ["LIST_NFT_COLLECTIONS", "SHOW_NFT_COLLECTIONS"], | ||
description: | ||
"Fetches information about curated NFT collections on Ethereum", | ||
validate: async (runtime: IAgentRuntime, message: Memory) => { | ||
return message.content.text.toLowerCase().includes("nft collections"); | ||
}, | ||
handler: async (runtime: IAgentRuntime, message: Memory) => { | ||
try { | ||
const response = await nftCollectionProvider.get(runtime, message); | ||
await runtime.messageManager.createMemory({ | ||
id: message.id, | ||
content: { text: response }, | ||
roomId: message.roomId, | ||
userId: message.userId, | ||
agentId: runtime.agentId, | ||
}); | ||
return true; | ||
} catch (error) { | ||
console.error("Error fetching NFT collections:", error); | ||
await runtime.messageManager.createMemory({ | ||
id: message.id, | ||
content: { text: "Failed to fetch NFT collection data." }, | ||
roomId: message.roomId, | ||
userId: message.userId, | ||
agentId: runtime.agentId, | ||
}); | ||
return false; | ||
} | ||
}, | ||
examples: [ | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "Can you tell me about the top NFT collections?", | ||
}, | ||
}, | ||
{ | ||
user: "{{user2}}", | ||
content: { | ||
text: "Certainly! Here are the top NFT collections on Ethereum:", | ||
action: "GET_NFT_COLLECTIONS", | ||
}, | ||
}, | ||
], | ||
], | ||
}; |
119 changes: 119 additions & 0 deletions
119
packages/plugin-nft-collections/src/actions/sweep-floor.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import { Action, IAgentRuntime, Memory, State } from "@ai16z/eliza"; | ||
import { NFTService } from "../types"; | ||
|
||
// Helper function to extract NFT details from the message | ||
function extractNFTDetails(text: string): { | ||
collectionAddress: string | null; | ||
quantity: number; | ||
} { | ||
const addressMatch = text.match(/0x[a-fA-F0-9]{40}/); | ||
const quantityMatch = text.match(/\d+/); | ||
|
||
return { | ||
collectionAddress: addressMatch ? addressMatch[0] : null, | ||
quantity: quantityMatch ? parseInt(quantityMatch[0]) : 1, | ||
}; | ||
} | ||
|
||
export const sweepFloorAction: Action = { | ||
name: "SWEEP_FLOOR_NFT", | ||
similes: ["BUY_FLOOR_NFT", "PURCHASE_FLOOR_NFT"], | ||
description: | ||
"Sweeps the floor of a specified EVM NFT collection by purchasing the lowest-priced available NFTs.", | ||
|
||
validate: async (runtime: IAgentRuntime, message: Memory) => { | ||
const content = message.content.text.toLowerCase(); | ||
return ( | ||
(content.includes("sweep") || content.includes("buy")) && | ||
content.includes("nft") && | ||
(content.includes("0x") || content.includes("floor")) | ||
); | ||
}, | ||
|
||
handler: async (runtime: IAgentRuntime, message: Memory, state?: State) => { | ||
try { | ||
const { collectionAddress, quantity } = extractNFTDetails( | ||
message.content.text | ||
); | ||
|
||
if (!collectionAddress) { | ||
throw new Error("No valid collection address found in message"); | ||
} | ||
|
||
const nftService = runtime.services.get("nft") as any as NFTService; | ||
if (!nftService) { | ||
throw new Error("NFT service not found"); | ||
} | ||
|
||
// Get floor listings sorted by price | ||
const floorListings = await nftService.getFloorListings({ | ||
collection: collectionAddress, | ||
limit: quantity, | ||
sortBy: "price", | ||
}); | ||
|
||
if (floorListings.length < quantity) { | ||
throw new Error( | ||
`Only ${floorListings.length} NFTs available at floor price` | ||
); | ||
} | ||
|
||
// Execute the buy transaction | ||
const result = await nftService.executeBuy({ | ||
listings: floorListings, | ||
taker: message.userId, // Assuming userId is the wallet address | ||
}); | ||
|
||
const totalPrice = floorListings.reduce( | ||
(sum, listing) => sum + listing.price, | ||
0 | ||
); | ||
const response = | ||
`Successfully initiated sweep of ${quantity} NFTs from collection ${collectionAddress}:\n` + | ||
`• Total Cost: ${totalPrice} ETH\n` + | ||
`• Average Price: ${(totalPrice / quantity).toFixed(4)} ETH\n` + | ||
`• Transaction Path: ${result.path}\n` + | ||
`• Status: ${result.steps.map((step) => `${step.action} - ${step.status}`).join(", ")}`; | ||
|
||
await runtime.messageManager.createMemory({ | ||
id: message.id, | ||
content: { text: response }, | ||
roomId: message.roomId, | ||
userId: message.userId, | ||
agentId: runtime.agentId, | ||
}); | ||
|
||
return true; | ||
} catch (error) { | ||
console.error("Floor sweep failed:", error); | ||
await runtime.messageManager.createMemory({ | ||
id: message.id, | ||
content: { | ||
text: `Failed to sweep floor NFTs: ${error.message}`, | ||
}, | ||
roomId: message.roomId, | ||
userId: message.userId, | ||
agentId: runtime.agentId, | ||
}); | ||
return false; | ||
} | ||
}, | ||
|
||
examples: [ | ||
[ | ||
{ | ||
user: "{{user1}}", | ||
content: { | ||
text: "Sweep 5 NFTs from collection 0x1234...abcd at floor price", | ||
}, | ||
}, | ||
{ | ||
user: "{{user2}}", | ||
content: { | ||
text: "Executing floor sweep for 5 NFTs...", | ||
action: "SWEEP_FLOOR_NFT", | ||
}, | ||
}, | ||
], | ||
], | ||
}; |
54 changes: 54 additions & 0 deletions
54
packages/plugin-nft-collections/src/evaluators/nft-knowledge.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { Evaluator, IAgentRuntime, Memory, State } from "@ai16z/eliza"; | ||
import { NFTKnowledge } from "../types"; | ||
|
||
export const nftKnowledgeEvaluator: Evaluator = { | ||
name: "nft-collection-evaluator", | ||
description: "Evaluates NFT-related content in messages", | ||
similes: ["nft-evaluator", "nft-knowledge"], | ||
alwaysRun: false, | ||
validate: async (runtime: IAgentRuntime, message: Memory) => { | ||
const content = message.content.text.toLowerCase(); | ||
return content.includes("nft") || content.includes("collection"); | ||
}, | ||
handler: async (runtime: IAgentRuntime, message: Memory, state: State) => { | ||
const content = message.content.text.toLowerCase(); | ||
|
||
// Extract relevant NFT information | ||
const extractedInfo: NFTKnowledge = { | ||
mentionsCollection: | ||
content.includes("collection") || content.includes("nft"), | ||
mentionsFloorPrice: | ||
content.includes("floor price") || content.includes("floor"), | ||
mentionsVolume: | ||
content.includes("volume") || | ||
content.includes("trading volume"), | ||
mentionsRarity: | ||
content.includes("rare") || content.includes("rarity"), | ||
}; | ||
|
||
// Update state with extracted information | ||
return { | ||
...state, | ||
nftKnowledge: extractedInfo, | ||
}; | ||
}, | ||
examples: [ | ||
{ | ||
context: "Evaluating NFT-related content in messages", | ||
messages: [ | ||
{ | ||
user: "{{user1}}", | ||
content: { text: "Tell me about NFT collections" }, | ||
}, | ||
{ | ||
user: "{{user2}}", | ||
content: { | ||
text: "I'll help you understand NFT collections.", | ||
}, | ||
}, | ||
], | ||
outcome: | ||
"The message contains NFT-related content and should be evaluated.", | ||
}, | ||
], | ||
}; |
Oops, something went wrong.