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 {