From dab71256df7708cc80abbd0b45bb87436d064b77 Mon Sep 17 00:00:00 2001 From: JSon <xwxtwd@gmail.com> Date: Fri, 20 Dec 2024 22:43:17 +0800 Subject: [PATCH 1/6] feat(plugin-nft-generation): add mint NFT with collection address action --- .../src/actions/mintNFTAction.ts | 381 ++++++++++++++++++ .../src/actions/nftCollectionGeneration.ts | 290 +++++++++++++ packages/plugin-nft-generation/src/index.ts | 189 +-------- .../src/provider/wallet/walletSolana.ts | 4 + 4 files changed, 679 insertions(+), 185 deletions(-) create mode 100644 packages/plugin-nft-generation/src/actions/mintNFTAction.ts create mode 100644 packages/plugin-nft-generation/src/actions/nftCollectionGeneration.ts diff --git a/packages/plugin-nft-generation/src/actions/mintNFTAction.ts b/packages/plugin-nft-generation/src/actions/mintNFTAction.ts new file mode 100644 index 00000000000..15515337159 --- /dev/null +++ b/packages/plugin-nft-generation/src/actions/mintNFTAction.ts @@ -0,0 +1,381 @@ +import { + Action, + composeContext, + Content, + elizaLogger, + generateObjectDeprecated, + getEmbeddingZeroVector, + HandlerCallback, + IAgentRuntime, + Memory, + ModelClass, + State, + stringToUuid, +} from "@ai16z/eliza"; +import { createNFT } from "../handlers/createNFT.ts"; +import { verifyNFT } from "../handlers/verifyNFT.ts"; +import { sleep } from "../index.ts"; +import WalletSolana from "../provider/wallet/walletSolana.ts"; +import { PublicKey } from "@solana/web3.js"; + +const mintTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined. + +Example response: +\`\`\`json +{ + "collectionAddress": "D8j4ubQ3MKwmAqiJw83qT7KQNKjhsuoC7zJJdJa5BkvS", +} +\`\`\` + +{{message}} + +Given the recent messages, extract the following information about the requested mint nft: +- collection contract address + +Respond with a JSON markdown block containing only the extracted values.`; + +export interface MintContent extends Content { + collectionAddress: string; +} + +function isMintNFTContent( + runtime: IAgentRuntime, + content: any +): content is MintContent { + console.log("Content for mint", content); + return typeof content.collectionAddress === "string"; +} + +const mintNFTAction: Action = { + name: "MINT_NFT", + similes: [ + "NFT_MINTING", + "NFT_CREATION", + "CREATE_NFT", + "GENERATE_NFT", + "MINT_TOKEN", + "CREATE_TOKEN", + "MAKE_NFT", + "TOKEN_GENERATION", + ], + description: "Mint NFTs for the collection", + validate: async (runtime: IAgentRuntime, _message: Memory) => { + const AwsAccessKeyIdOk = !!runtime.getSetting("AWS_ACCESS_KEY_ID"); + const AwsSecretAccessKeyOk = !!runtime.getSetting( + "AWS_SECRET_ACCESS_KEY" + ); + const AwsRegionOk = !!runtime.getSetting("AWS_REGION"); + const AwsS3BucketOk = !!runtime.getSetting("AWS_S3_BUCKET"); + + return ( + AwsAccessKeyIdOk || + AwsSecretAccessKeyOk || + AwsRegionOk || + AwsS3BucketOk + ); + }, + handler: async ( + runtime: IAgentRuntime, + message: Memory, + state: State, + options: { [key: string]: unknown }, + callback: HandlerCallback + ) => { + try { + elizaLogger.log("Composing state for message:", message); + const userId = runtime.agentId; + const agentName = runtime.character.name; + const roomId = stringToUuid("nft_generate_room-" + agentName); + + const memory: Memory = { + agentId: userId, + userId, + roomId, + content: { + text: message.content.text, + source: "nft-generator", + }, + createdAt: Date.now(), + embedding: getEmbeddingZeroVector(), + }; + const state = await runtime.composeState(memory, { + message: message.content.text, + }); + + elizaLogger.log("state:", state); + + // Compose transfer context + const transferContext = composeContext({ + state, + template: mintTemplate, + }); + + const content = await generateObjectDeprecated({ + runtime, + context: transferContext, + modelClass: ModelClass.LARGE, + }); + + elizaLogger.log("generateObjectDeprecated:", transferContext); + + if (!isMintNFTContent(runtime, content)) { + elizaLogger.error("Invalid content for MINT_NFT action."); + if (callback) { + callback({ + text: "Unable to process mint request. Invalid content provided.", + content: { error: "Invalid mint content" }, + }); + } + return false; + } + + elizaLogger.log("mint content", content); + + const publicKey = runtime.getSetting("SOLANA_PUBLIC_KEY"); + const privateKey = runtime.getSetting("SOLANA_PRIVATE_KEY"); + + const wallet = new WalletSolana( + new PublicKey(publicKey), + privateKey + ); + + const collectionInfo = await wallet.fetchDigitalAsset( + content.collectionAddress + ); + elizaLogger.log("Collection Info", collectionInfo); + const metadata = collectionInfo.metadata; + if (metadata.collection?.["value"]) { + callback({ + text: `Unable to process mint request. Invalid collection address ${content.collectionAddress}.`, + content: { error: "Invalid collection address." }, + }); + return false; + } + if (metadata) { + elizaLogger.log("nft params", {}); + const nftRes = await createNFT({ + runtime, + collectionName: metadata.name, + collectionAddress: content.collectionAddress, + collectionAdminPublicKey: metadata.updateAuthority, + collectionFee: metadata.sellerFeeBasisPoints, + tokenId: 1, + }); + + elizaLogger.log("NFT Address:", nftRes); + + if (nftRes) { + callback({ + text: `Congratulations to you! 🎉🎉🎉 \nCollection Address: ${content.collectionAddress}\n NFT Address: ${nftRes.address}\n NFT Link: ${nftRes.link}`, //caption.description, + attachments: [], + }); + await sleep(15000); + await verifyNFT({ + runtime, + collectionAddress: content.collectionAddress, + NFTAddress: nftRes.address, + }); + } else { + callback({ + text: `Mint NFT Error in ${content.collectionAddress}.`, + content: { error: "Mint NFT Error." }, + }); + return false; + } + } else { + callback({ + text: "Unable to process mint request. Invalid collection address.", + content: { error: "Invalid collection address." }, + }); + return false; + } + + // + // const userId = runtime.agentId; + // elizaLogger.log("User ID:", userId); + // + // const collectionAddressRes = await createCollection({ + // runtime, + // collectionName: runtime.character.name, + // }); + // + // const collectionInfo = collectionAddressRes.collectionInfo; + // + // elizaLogger.log("Collection Address:", collectionAddressRes); + + // + // elizaLogger.log("NFT Address:", nftRes); + // + // + // callback({ + // text: `Congratulations to you! 🎉🎉🎉 \nCollection : ${collectionAddressRes.link}\n NFT: ${nftRes.link}`, //caption.description, + // attachments: [], + // }); + // await sleep(15000); + // await verifyNFT({ + // runtime, + // collectionAddress: collectionAddressRes.address, + // NFTAddress: nftRes.address, + // }); + return []; + } catch (e: any) { + console.log(e); + } + + // callback(); + }, + examples: [ + [ + { + user: "{{user1}}", + content: { + text: "mint nft for collection: D8j4ubQ3MKwmAqiJw83qT7KQNKjhsuoC7zJJdJa5BkvS", + }, + }, + { + user: "{{agentName}}", + content: { + text: "I've minted a new NFT in your specified collection.", + action: "MINT_NFT", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Could you create an NFT in collection D8j4ubQ3MKwmAqiJw83qT7KQNKjhsuoC7zJJdJa5BkvS?", + }, + }, + { + user: "{{agentName}}", + content: { + text: "Successfully minted your NFT in the specified collection.", + action: "MINT_NFT", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Please mint a new token in D8j4ubQ3MKwmAqiJw83qT7KQNKjhsuoC7zJJdJa5BkvS collection", + }, + }, + { + user: "{{agentName}}", + content: { + text: "Your NFT has been minted in the collection successfully.", + action: "MINT_NFT", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Generate NFT for D8j4ubQ3MKwmAqiJw83qT7KQNKjhsuoC7zJJdJa5BkvS", + }, + }, + { + user: "{{agentName}}", + content: { + text: "I've generated and minted your NFT in the collection.", + action: "MINT_NFT", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "I want to mint an NFT in collection D8j4ubQ3MKwmAqiJw83qT7KQNKjhsuoC7zJJdJa5BkvS", + }, + }, + { + user: "{{agentName}}", + content: { + text: "Your NFT has been successfully minted in the collection.", + action: "MINT_NFT", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Create a new NFT token in D8j4ubQ3MKwmAqiJw83qT7KQNKjhsuoC7zJJdJa5BkvS collection", + }, + }, + { + user: "{{agentName}}", + content: { + text: "The NFT has been created in your specified collection.", + action: "MINT_NFT", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Issue an NFT for collection D8j4ubQ3MKwmAqiJw83qT7KQNKjhsuoC7zJJdJa5BkvS", + }, + }, + { + user: "{{agentName}}", + content: { + text: "I've issued your NFT in the requested collection.", + action: "MINT_NFT", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Make a new NFT in D8j4ubQ3MKwmAqiJw83qT7KQNKjhsuoC7zJJdJa5BkvS", + }, + }, + { + user: "{{agentName}}", + content: { + text: "Your new NFT has been minted in the collection.", + action: "MINT_NFT", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Can you mint an NFT for D8j4ubQ3MKwmAqiJw83qT7KQNKjhsuoC7zJJdJa5BkvS collection?", + }, + }, + { + user: "{{agentName}}", + content: { + text: "I've completed minting your NFT in the collection.", + action: "MINT_NFT", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Add a new NFT to collection D8j4ubQ3MKwmAqiJw83qT7KQNKjhsuoC7zJJdJa5BkvS", + }, + }, + { + user: "{{agentName}}", + content: { + text: "A new NFT has been added to your collection.", + action: "MINT_NFT", + }, + }, + ], + ], +} as Action; + +export default mintNFTAction; diff --git a/packages/plugin-nft-generation/src/actions/nftCollectionGeneration.ts b/packages/plugin-nft-generation/src/actions/nftCollectionGeneration.ts new file mode 100644 index 00000000000..9973d734076 --- /dev/null +++ b/packages/plugin-nft-generation/src/actions/nftCollectionGeneration.ts @@ -0,0 +1,290 @@ +import { + Action, + elizaLogger, + HandlerCallback, + IAgentRuntime, + Memory, + State, +} from "@ai16z/eliza"; +import { createCollection } from "../handlers/createCollection.ts"; + +const nftCollectionGeneration: Action = { + name: "GENERATE_COLLECTION", + similes: [ + "COLLECTION_GENERATION", + "COLLECTION_GEN", + "CREATE_COLLECTION", + "MAKE_COLLECTION", + "GENERATE_COLLECTION", + ], + description: "Generate an NFT collection for the message", + validate: async (runtime: IAgentRuntime, _message: Memory) => { + const awsAccessKeyIdOk = !!runtime.getSetting("AWS_ACCESS_KEY_ID"); + const awsSecretAccessKeyOk = !!runtime.getSetting( + "AWS_SECRET_ACCESS_KEY" + ); + const awsRegionOk = !!runtime.getSetting("AWS_REGION"); + const awsS3BucketOk = !!runtime.getSetting("AWS_S3_BUCKET"); + const solanaPrivateKeyOk = !!runtime.getSetting("SOLANA_PRIVATE_KEY"); + const solanaPublicKeyOk = !!runtime.getSetting("SOLANA_PUBLIC_KEY"); + + return ( + awsAccessKeyIdOk || + awsSecretAccessKeyOk || + awsRegionOk || + awsS3BucketOk || + solanaPrivateKeyOk || + solanaPublicKeyOk + ); + }, + handler: async ( + runtime: IAgentRuntime, + message: Memory, + state: State, + options: { [key: string]: unknown }, + callback: HandlerCallback + ) => { + try { + elizaLogger.log("Composing state for message:", message); + const collectionAddressRes = await createCollection({ + runtime, + collectionName: runtime.character.name, + }); + elizaLogger.log("Collection Info:", collectionAddressRes); + if (callback) { + callback({ + text: `Congratulations to you! 🎉🎉🎉 \nCollection Link : ${collectionAddressRes.link}\n Address: ${collectionAddressRes.address}`, //caption.description, + attachments: [], + }); + } + return []; + } catch (e: any) { + console.log(e); + throw e; + } + }, + examples: [ + [ + { + user: "{{user1}}", + content: { text: "Generate a collection" }, + }, + { + user: "{{agentName}}", + content: { + text: "Here's the collection you requested.", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { text: "Generate a collection using {{agentName}}" }, + }, + { + user: "{{agentName}}", + content: { + text: "We've successfully created a collection.", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { text: "Create a collection using {{agentName}}" }, + }, + { + user: "{{agentName}}", + content: { + text: "Here's the collection you requested.", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { text: "Build a Collection" }, + }, + { + user: "{{agentName}}", + content: { + text: "The collection has been successfully built.", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { text: "Assemble a collection with {{agentName}}" }, + }, + { + user: "{{agentName}}", + content: { + text: "The collection has been assembled", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { text: "Make a collection" }, + }, + { + user: "{{agentName}}", + content: { + text: "The collection has been produced successfully.", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Could you create a new collection for my photos?", + }, + }, + { + user: "{{agentName}}", + content: { + text: "I've created a new collection for your photos.", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "I need a collection for organizing my music", + }, + }, + { + user: "{{agentName}}", + content: { + text: "Your music collection has been generated.", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Please set up a collection for my documents", + }, + }, + { + user: "{{agentName}}", + content: { + text: "I've set up a new collection for your documents.", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { text: "Start a new collection for me" }, + }, + { + user: "{{agentName}}", + content: { + text: "Your new collection has been created.", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "I'd like to make a collection of my recipes", + }, + }, + { + user: "{{agentName}}", + content: { + text: "I've generated a collection for your recipes.", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Can you generate a collection for my artwork?", + }, + }, + { + user: "{{agentName}}", + content: { + text: "Your artwork collection has been generated.", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { text: "Initialize a new collection please" }, + }, + { + user: "{{agentName}}", + content: { + text: "I've initialized a new collection for you.", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { text: "Create a collection for my travel memories" }, + }, + { + user: "{{agentName}}", + content: { + text: "Your travel memories collection has been created.", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Would you make a collection for my projects?", + }, + }, + { + user: "{{agentName}}", + content: { + text: "I've made a collection for your projects.", + action: "GENERATE_COLLECTION", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { text: "Set up a collection for my bookmarks" }, + }, + { + user: "{{agentName}}", + content: { + text: "Your bookmarks collection has been set up.", + action: "GENERATE_COLLECTION", + }, + }, + ], + ], +} as Action; + +export default nftCollectionGeneration; diff --git a/packages/plugin-nft-generation/src/index.ts b/packages/plugin-nft-generation/src/index.ts index 07a147ef0d6..5540ec3a5b7 100644 --- a/packages/plugin-nft-generation/src/index.ts +++ b/packages/plugin-nft-generation/src/index.ts @@ -1,16 +1,6 @@ -import { - Action, - elizaLogger, - HandlerCallback, - IAgentRuntime, - Memory, - Plugin, - State, -} from "@elizaos/core"; - -import { createCollection } from "./handlers/createCollection.ts"; -import { createNFT } from "./handlers/createNFT.ts"; -import { verifyNFT } from "./handlers/verifyNFT.ts"; +import { Plugin } from "@ai16z/eliza"; +import nftCollectionGeneration from "./actions/nftCollectionGeneration.ts"; +import mintNFTAction from "./actions/mintNFTAction.ts"; export * from "./provider/wallet/walletSolana.ts"; export * from "./api.ts"; @@ -21,181 +11,10 @@ export async function sleep(ms: number = 3000) { }); } -const nftCollectionGeneration: Action = { - name: "GENERATE_COLLECTION", - similes: [ - "COLLECTION_GENERATION", - "COLLECTION_GEN", - "CREATE_COLLECTION", - "MAKE_COLLECTION", - "GENERATE_COLLECTION", - ], - description: "Generate an NFT collection for the message", - validate: async (runtime: IAgentRuntime, _message: Memory) => { - const AwsAccessKeyIdOk = !!runtime.getSetting("AWS_ACCESS_KEY_ID"); - const AwsSecretAccessKeyOk = !!runtime.getSetting( - "AWS_SECRET_ACCESS_KEY" - ); - const AwsRegionOk = !!runtime.getSetting("AWS_REGION"); - const AwsS3BucketOk = !!runtime.getSetting("AWS_S3_BUCKET"); - - return ( - AwsAccessKeyIdOk || - AwsSecretAccessKeyOk || - AwsRegionOk || - AwsS3BucketOk - ); - }, - handler: async ( - runtime: IAgentRuntime, - message: Memory, - state: State, - options: { [key: string]: unknown }, - callback: HandlerCallback - ) => { - try { - elizaLogger.log("Composing state for message:", message); - const userId = runtime.agentId; - elizaLogger.log("User ID:", userId); - - const collectionAddressRes = await createCollection({ - runtime, - collectionName: runtime.character.name, - }); - - const collectionInfo = collectionAddressRes.collectionInfo; - - elizaLogger.log("Collection Address:", collectionAddressRes); - - const nftRes = await createNFT({ - runtime, - collectionName: collectionInfo.name, - collectionAddress: collectionAddressRes.address, - collectionAdminPublicKey: collectionInfo.adminPublicKey, - collectionFee: collectionInfo.fee, - tokenId: 1, - }); - - elizaLogger.log("NFT Address:", nftRes); - - callback({ - text: `Congratulations to you! 🎉🎉🎉 \nCollection : ${collectionAddressRes.link}\n NFT: ${nftRes.link}`, //caption.description, - attachments: [], - }); - await sleep(15000); - await verifyNFT({ - runtime, - collectionAddress: collectionAddressRes.address, - NFTAddress: nftRes.address, - }); - return []; - } catch (e: any) { - console.log(e); - } - - // callback(); - }, - examples: [ - // TODO: We want to generate images in more abstract ways, not just when asked to generate an image - - [ - { - user: "{{user1}}", - content: { text: "Generate a collection" }, - }, - { - user: "{{agentName}}", - content: { - text: "Here's the collection you requested.", - action: "GENERATE_COLLECTION", - }, - }, - ], - [ - { - user: "{{user1}}", - content: { text: "Generate a collection using {{agentName}}" }, - }, - { - user: "{{agentName}}", - content: { - text: "We've successfully created a collection.", - action: "GENERATE_COLLECTION", - }, - }, - ], - [ - { - user: "{{user1}}", - content: { text: "Create a collection using {{agentName}}" }, - }, - { - user: "{{agentName}}", - content: { - text: "Here's the collection you requested.", - action: "GENERATE_COLLECTION", - }, - }, - ], - [ - { - user: "{{user1}}", - content: { text: "Build a Collection" }, - }, - { - user: "{{agentName}}", - content: { - text: "The collection has been successfully built.", - action: "GENERATE_COLLECTION", - }, - }, - ], - [ - { - user: "{{user1}}", - content: { text: "Assemble a collection with {{agentName}}" }, - }, - { - user: "{{agentName}}", - content: { - text: "The collection has been assembled", - action: "GENERATE_COLLECTION", - }, - }, - ], - [ - { - user: "{{user1}}", - content: { text: "Make a collection" }, - }, - { - user: "{{agentName}}", - content: { - text: "The collection has been produced successfully.", - action: "GENERATE_COLLECTION", - }, - }, - ], - [ - { - user: "{{user1}}", - content: { text: "Compile a collection" }, - }, - { - user: "{{agentName}}", - content: { - text: "The collection has been compiled.", - action: "GENERATE_COLLECTION", - }, - }, - ], - ], -} as Action; - export const nftGenerationPlugin: Plugin = { name: "nftCollectionGeneration", description: "Generate NFT Collections", - actions: [nftCollectionGeneration], + actions: [nftCollectionGeneration, mintNFTAction], evaluators: [], providers: [], }; diff --git a/packages/plugin-nft-generation/src/provider/wallet/walletSolana.ts b/packages/plugin-nft-generation/src/provider/wallet/walletSolana.ts index 2bfeb85ca67..74a605c9c2b 100644 --- a/packages/plugin-nft-generation/src/provider/wallet/walletSolana.ts +++ b/packages/plugin-nft-generation/src/provider/wallet/walletSolana.ts @@ -10,6 +10,7 @@ import { createNft, findMetadataPda, mplTokenMetadata, + fetchDigitalAsset, updateV1, verifyCollectionV1, } from "@metaplex-foundation/mpl-token-metadata"; @@ -55,6 +56,9 @@ export class WalletSolana { this.umi = umi; } + async fetchDigitalAsset (address: string) { + return fetchDigitalAsset(this.umi, publicKey(address)) + } async getBalance() { const balance = await this.connection.getBalance(this.walletPublicKey); return { From a06e10945fb19d61080d5747608614743141bdca Mon Sep 17 00:00:00 2001 From: JSon <xwxtwd@gmail.com> Date: Fri, 20 Dec 2024 23:00:40 +0800 Subject: [PATCH 2/6] feat(plugin-nft-generation): change mintTemplate. --- .../src/actions/mintNFTAction.ts | 70 +++++++------------ 1 file changed, 24 insertions(+), 46 deletions(-) diff --git a/packages/plugin-nft-generation/src/actions/mintNFTAction.ts b/packages/plugin-nft-generation/src/actions/mintNFTAction.ts index 15515337159..a2a026a3aa1 100644 --- a/packages/plugin-nft-generation/src/actions/mintNFTAction.ts +++ b/packages/plugin-nft-generation/src/actions/mintNFTAction.ts @@ -27,12 +27,15 @@ Example response: } \`\`\` -{{message}} +{{recentMessages}} Given the recent messages, extract the following information about the requested mint nft: - collection contract address -Respond with a JSON markdown block containing only the extracted values.`; +Respond with a JSON markdown block containing only the extracted values. + +Note: Make sure to extract the collection address from the most recent messages whenever possible.` + export interface MintContent extends Content { collectionAddress: string; @@ -87,22 +90,25 @@ const mintNFTAction: Action = { const agentName = runtime.character.name; const roomId = stringToUuid("nft_generate_room-" + agentName); - const memory: Memory = { - agentId: userId, - userId, - roomId, - content: { - text: message.content.text, - source: "nft-generator", - }, - createdAt: Date.now(), - embedding: getEmbeddingZeroVector(), - }; - const state = await runtime.composeState(memory, { - message: message.content.text, - }); - - elizaLogger.log("state:", state); + // const memory: Memory = { + // agentId: userId, + // userId, + // roomId, + // content: { + // text: message.content.text, + // source: "nft-generator", + // }, + // createdAt: Date.now(), + // embedding: getEmbeddingZeroVector(), + // }; + // const state = await runtime.composeState(memory, { + // message: message.content.text, + // }); + if (!state) { + state = (await runtime.composeState(message)) as State; + } else { + state = await runtime.updateRecentMessageState(state); + } // Compose transfer context const transferContext = composeContext({ @@ -189,34 +195,6 @@ const mintNFTAction: Action = { }); return false; } - - // - // const userId = runtime.agentId; - // elizaLogger.log("User ID:", userId); - // - // const collectionAddressRes = await createCollection({ - // runtime, - // collectionName: runtime.character.name, - // }); - // - // const collectionInfo = collectionAddressRes.collectionInfo; - // - // elizaLogger.log("Collection Address:", collectionAddressRes); - - // - // elizaLogger.log("NFT Address:", nftRes); - // - // - // callback({ - // text: `Congratulations to you! 🎉🎉🎉 \nCollection : ${collectionAddressRes.link}\n NFT: ${nftRes.link}`, //caption.description, - // attachments: [], - // }); - // await sleep(15000); - // await verifyNFT({ - // runtime, - // collectionAddress: collectionAddressRes.address, - // NFTAddress: nftRes.address, - // }); return []; } catch (e: any) { console.log(e); From cf0dc4f3c5362e391530e933df329ecb4a27ee12 Mon Sep 17 00:00:00 2001 From: JSon <xwxtwd@gmail.com> Date: Fri, 20 Dec 2024 23:08:32 +0800 Subject: [PATCH 3/6] chore --- .../src/actions/mintNFTAction.ts | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/packages/plugin-nft-generation/src/actions/mintNFTAction.ts b/packages/plugin-nft-generation/src/actions/mintNFTAction.ts index a2a026a3aa1..ecb8a47d619 100644 --- a/packages/plugin-nft-generation/src/actions/mintNFTAction.ts +++ b/packages/plugin-nft-generation/src/actions/mintNFTAction.ts @@ -4,13 +4,11 @@ import { Content, elizaLogger, generateObjectDeprecated, - getEmbeddingZeroVector, HandlerCallback, IAgentRuntime, Memory, ModelClass, State, - stringToUuid, } from "@ai16z/eliza"; import { createNFT } from "../handlers/createNFT.ts"; import { verifyNFT } from "../handlers/verifyNFT.ts"; @@ -34,8 +32,7 @@ Given the recent messages, extract the following information about the requested Respond with a JSON markdown block containing only the extracted values. -Note: Make sure to extract the collection address from the most recent messages whenever possible.` - +Note: Make sure to extract the collection address from the most recent messages whenever possible.`; export interface MintContent extends Content { collectionAddress: string; @@ -86,24 +83,6 @@ const mintNFTAction: Action = { ) => { try { elizaLogger.log("Composing state for message:", message); - const userId = runtime.agentId; - const agentName = runtime.character.name; - const roomId = stringToUuid("nft_generate_room-" + agentName); - - // const memory: Memory = { - // agentId: userId, - // userId, - // roomId, - // content: { - // text: message.content.text, - // source: "nft-generator", - // }, - // createdAt: Date.now(), - // embedding: getEmbeddingZeroVector(), - // }; - // const state = await runtime.composeState(memory, { - // message: message.content.text, - // }); if (!state) { state = (await runtime.composeState(message)) as State; } else { From 2d6ed382883ad62dfd6c826c440b441468a555d9 Mon Sep 17 00:00:00 2001 From: JSon <xwxtwd@gmail.com> Date: Sun, 22 Dec 2024 00:46:33 +0800 Subject: [PATCH 4/6] feat: 1.using generateObject and templated type safe schema. 2.naming convention camelCase. 3.create a template and type file --- .../src/actions/mintNFTAction.ts | 73 +++++++------------ .../plugin-nft-generation/src/templates.ts | 18 +++++ packages/plugin-nft-generation/src/types.ts | 11 +++ 3 files changed, 57 insertions(+), 45 deletions(-) create mode 100644 packages/plugin-nft-generation/src/templates.ts create mode 100644 packages/plugin-nft-generation/src/types.ts diff --git a/packages/plugin-nft-generation/src/actions/mintNFTAction.ts b/packages/plugin-nft-generation/src/actions/mintNFTAction.ts index ecb8a47d619..a6556b5cb75 100644 --- a/packages/plugin-nft-generation/src/actions/mintNFTAction.ts +++ b/packages/plugin-nft-generation/src/actions/mintNFTAction.ts @@ -1,9 +1,8 @@ import { Action, composeContext, - Content, elizaLogger, - generateObjectDeprecated, + generateObject, HandlerCallback, IAgentRuntime, Memory, @@ -15,34 +14,10 @@ import { verifyNFT } from "../handlers/verifyNFT.ts"; import { sleep } from "../index.ts"; import WalletSolana from "../provider/wallet/walletSolana.ts"; import { PublicKey } from "@solana/web3.js"; +import { mintNFTTemplate } from "../templates.ts"; +import { MintNFTContent, MintNFTSchema } from "../types.ts"; -const mintTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined. - -Example response: -\`\`\`json -{ - "collectionAddress": "D8j4ubQ3MKwmAqiJw83qT7KQNKjhsuoC7zJJdJa5BkvS", -} -\`\`\` - -{{recentMessages}} - -Given the recent messages, extract the following information about the requested mint nft: -- collection contract address - -Respond with a JSON markdown block containing only the extracted values. - -Note: Make sure to extract the collection address from the most recent messages whenever possible.`; - -export interface MintContent extends Content { - collectionAddress: string; -} - -function isMintNFTContent( - runtime: IAgentRuntime, - content: any -): content is MintContent { - console.log("Content for mint", content); +function isMintNFTContent(content: any): content is MintNFTContent { return typeof content.collectionAddress === "string"; } @@ -60,18 +35,26 @@ const mintNFTAction: Action = { ], description: "Mint NFTs for the collection", validate: async (runtime: IAgentRuntime, _message: Memory) => { - const AwsAccessKeyIdOk = !!runtime.getSetting("AWS_ACCESS_KEY_ID"); - const AwsSecretAccessKeyOk = !!runtime.getSetting( + const awsAccessKeyIdOk = !!runtime.getSetting("AWS_ACCESS_KEY_ID"); + const awsSecretAccessKeyOk = !!runtime.getSetting( "AWS_SECRET_ACCESS_KEY" ); - const AwsRegionOk = !!runtime.getSetting("AWS_REGION"); - const AwsS3BucketOk = !!runtime.getSetting("AWS_S3_BUCKET"); + const awsRegionOk = !!runtime.getSetting("AWS_REGION"); + const awsS3BucketOk = !!runtime.getSetting("AWS_S3_BUCKET"); + const solanaAdminPrivateKeyOk = !!runtime.getSetting( + "SOLANA_ADMIN_PRIVATE_KEY" + ); + const solanaAdminPublicKeyOk = !!runtime.getSetting( + "SOLANA_ADMIN_PUBLIC_KEY" + ); return ( - AwsAccessKeyIdOk || - AwsSecretAccessKeyOk || - AwsRegionOk || - AwsS3BucketOk + awsAccessKeyIdOk || + awsSecretAccessKeyOk || + awsRegionOk || + awsS3BucketOk || + solanaAdminPrivateKeyOk || + solanaAdminPublicKeyOk ); }, handler: async ( @@ -92,18 +75,20 @@ const mintNFTAction: Action = { // Compose transfer context const transferContext = composeContext({ state, - template: mintTemplate, + template: mintNFTTemplate, }); - const content = await generateObjectDeprecated({ + const res = await generateObject({ runtime, context: transferContext, modelClass: ModelClass.LARGE, + schema: MintNFTSchema, }); + const content = res.object; - elizaLogger.log("generateObjectDeprecated:", transferContext); + elizaLogger.log("Generate Object:", content); - if (!isMintNFTContent(runtime, content)) { + if (!isMintNFTContent(content)) { elizaLogger.error("Invalid content for MINT_NFT action."); if (callback) { callback({ @@ -137,7 +122,6 @@ const mintNFTAction: Action = { return false; } if (metadata) { - elizaLogger.log("nft params", {}); const nftRes = await createNFT({ runtime, collectionName: metadata.name, @@ -176,10 +160,9 @@ const mintNFTAction: Action = { } return []; } catch (e: any) { - console.log(e); + elizaLogger.log(e); + throw e; } - - // callback(); }, examples: [ [ diff --git a/packages/plugin-nft-generation/src/templates.ts b/packages/plugin-nft-generation/src/templates.ts new file mode 100644 index 00000000000..8c6f9169edb --- /dev/null +++ b/packages/plugin-nft-generation/src/templates.ts @@ -0,0 +1,18 @@ + +export const mintNFTTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined. + +Example response: +\`\`\`json +{ + "collectionAddress": "D8j4ubQ3MKwmAqiJw83qT7KQNKjhsuoC7zJJdJa5BkvS", +} +\`\`\` + +{{recentMessages}} + +Given the recent messages, extract the following information about the requested mint nft: +- collection contract address + +Respond with a JSON markdown block containing only the extracted values. + +Note: Make sure to extract the collection address from the most recent messages whenever possible.`; diff --git a/packages/plugin-nft-generation/src/types.ts b/packages/plugin-nft-generation/src/types.ts new file mode 100644 index 00000000000..d422bdea218 --- /dev/null +++ b/packages/plugin-nft-generation/src/types.ts @@ -0,0 +1,11 @@ +import { z } from "zod"; +import { Content } from "@ai16z/eliza"; + + +export interface MintNFTContent extends Content { + collectionAddress: string; +} + +export const MintNFTSchema = z.object({ + collectionAddress: z.string(), +}); From 8eac64122f9c7af37761d412cddb4b39b50337a7 Mon Sep 17 00:00:00 2001 From: JSon <xwxtwd@gmail.com> Date: Sun, 22 Dec 2024 00:48:42 +0800 Subject: [PATCH 5/6] feat: Remove unnecessary logs --- packages/plugin-nft-generation/src/actions/mintNFTAction.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/plugin-nft-generation/src/actions/mintNFTAction.ts b/packages/plugin-nft-generation/src/actions/mintNFTAction.ts index a6556b5cb75..2d9f0fb2c91 100644 --- a/packages/plugin-nft-generation/src/actions/mintNFTAction.ts +++ b/packages/plugin-nft-generation/src/actions/mintNFTAction.ts @@ -99,7 +99,6 @@ const mintNFTAction: Action = { return false; } - elizaLogger.log("mint content", content); const publicKey = runtime.getSetting("SOLANA_PUBLIC_KEY"); const privateKey = runtime.getSetting("SOLANA_PRIVATE_KEY"); From ed68dc3c97bc510c3bb50ff3b5df4120b7df819d Mon Sep 17 00:00:00 2001 From: JSon <xwxtwd@gmail.com> Date: Mon, 23 Dec 2024 10:39:42 +0800 Subject: [PATCH 6/6] feat: ai16z -> elizaos --- packages/plugin-nft-generation/src/actions/mintNFTAction.ts | 2 +- .../src/actions/nftCollectionGeneration.ts | 2 +- packages/plugin-nft-generation/src/index.ts | 2 +- packages/plugin-nft-generation/src/types.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/plugin-nft-generation/src/actions/mintNFTAction.ts b/packages/plugin-nft-generation/src/actions/mintNFTAction.ts index 2d9f0fb2c91..61f4d70984e 100644 --- a/packages/plugin-nft-generation/src/actions/mintNFTAction.ts +++ b/packages/plugin-nft-generation/src/actions/mintNFTAction.ts @@ -8,7 +8,7 @@ import { Memory, ModelClass, State, -} from "@ai16z/eliza"; +} from "@elizaos/core"; import { createNFT } from "../handlers/createNFT.ts"; import { verifyNFT } from "../handlers/verifyNFT.ts"; import { sleep } from "../index.ts"; diff --git a/packages/plugin-nft-generation/src/actions/nftCollectionGeneration.ts b/packages/plugin-nft-generation/src/actions/nftCollectionGeneration.ts index 9973d734076..19e1fc3f880 100644 --- a/packages/plugin-nft-generation/src/actions/nftCollectionGeneration.ts +++ b/packages/plugin-nft-generation/src/actions/nftCollectionGeneration.ts @@ -5,7 +5,7 @@ import { IAgentRuntime, Memory, State, -} from "@ai16z/eliza"; +} from "@elizaos/core"; import { createCollection } from "../handlers/createCollection.ts"; const nftCollectionGeneration: Action = { diff --git a/packages/plugin-nft-generation/src/index.ts b/packages/plugin-nft-generation/src/index.ts index 5540ec3a5b7..55f3fe0e3e2 100644 --- a/packages/plugin-nft-generation/src/index.ts +++ b/packages/plugin-nft-generation/src/index.ts @@ -1,4 +1,4 @@ -import { Plugin } from "@ai16z/eliza"; +import { Plugin } from "@elizaos/core"; import nftCollectionGeneration from "./actions/nftCollectionGeneration.ts"; import mintNFTAction from "./actions/mintNFTAction.ts"; diff --git a/packages/plugin-nft-generation/src/types.ts b/packages/plugin-nft-generation/src/types.ts index d422bdea218..e00fe709d97 100644 --- a/packages/plugin-nft-generation/src/types.ts +++ b/packages/plugin-nft-generation/src/types.ts @@ -1,5 +1,5 @@ import { z } from "zod"; -import { Content } from "@ai16z/eliza"; +import { Content } from "@elizaos/core"; export interface MintNFTContent extends Content {