Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: solana token deploy using solana agent kit #1373

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"@elizaos/plugin-nft-generation": "workspace:*",
"@elizaos/plugin-node": "workspace:*",
"@elizaos/plugin-solana": "workspace:*",
"@elizaos/plugin-solana-agentkit": "workspace:*",
"@elizaos/plugin-starknet": "workspace:*",
"@elizaos/plugin-ton": "workspace:*",
"@elizaos/plugin-sui": "workspace:*",
Expand Down
4 changes: 4 additions & 0 deletions agent/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import { nearPlugin } from "@elizaos/plugin-near";
import { nftGenerationPlugin } from "@elizaos/plugin-nft-generation";
import { createNodePlugin } from "@elizaos/plugin-node";
import { solanaPlugin } from "@elizaos/plugin-solana";
import { solanaAgentkitPlguin } from "@elizaos/plugin-solana-agentkit";
import { suiPlugin } from "@elizaos/plugin-sui";
import { TEEMode, teePlugin } from "@elizaos/plugin-tee";
import { tonPlugin } from "@elizaos/plugin-ton";
Expand Down Expand Up @@ -486,6 +487,9 @@ export async function createAgent(
!getSecret(character, "WALLET_PUBLIC_KEY")?.startsWith("0x"))
? solanaPlugin
: null,
getSecret(character, "SOLANA_PRIVATE_KEY")
? solanaAgentkitPlguin
: null,
(getSecret(character, "NEAR_ADDRESS") ||
getSecret(character, "NEAR_WALLET_PUBLIC_KEY")) &&
getSecret(character, "NEAR_WALLET_SECRET_KEY")
Expand Down
6 changes: 6 additions & 0 deletions packages/plugin-solana-agentkit/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*

!dist/**
!package.json
!readme.md
!tsup.config.ts
3 changes: 3 additions & 0 deletions packages/plugin-solana-agentkit/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import eslintGlobalConfig from "../../eslint.config.mjs";

export default [...eslintGlobalConfig];
34 changes: 34 additions & 0 deletions packages/plugin-solana-agentkit/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "@elizaos/plugin-solana-agentkit",
"version": "0.1.7-alpha.1",
"main": "dist/index.js",
"type": "module",
"types": "dist/index.d.ts",
"dependencies": {
"@coral-xyz/anchor": "0.30.1",
"@elizaos/core": "workspace:*",
"@elizaos/plugin-tee": "workspace:*",
"@elizaos/plugin-trustdb": "workspace:*",
renlulu marked this conversation as resolved.
Show resolved Hide resolved
"@solana/spl-token": "0.4.9",
"@solana/web3.js": "1.95.8",
"bignumber": "1.1.0",
"bignumber.js": "9.1.2",
"bs58": "6.0.0",
"fomo-sdk-solana": "1.3.2",
"node-cache": "5.1.2",
"pumpdotfun-sdk": "1.3.2",
"solana-agent-kit": "^1.2.0",
"tsup": "8.3.5",
"vitest": "2.1.4"
},
"scripts": {
"build": "tsup --format esm --dts",
"dev": "tsup --format esm --dts --watch",
"lint": "eslint --fix --cache .",
"test": "vitest run"
},
"peerDependencies": {
"form-data": "4.0.1",
"whatwg-url": "7.1.0"
}
}
168 changes: 168 additions & 0 deletions packages/plugin-solana-agentkit/src/actions/createToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import {
ActionExample,
composeContext,
Content,
elizaLogger,
generateObjectDeprecated,
HandlerCallback,
IAgentRuntime,
Memory,
ModelClass,
State,
type Action,
} from "@elizaos/core";

import { SolanaAgentKit } from "solana-agent-kit";

export interface CreateTokenContent extends Content {
name: string;
uri: string;
symbol: string;
decimals: number;
initialSupply: number;
}

function isCreateTokenContent(content: any): content is CreateTokenContent {
elizaLogger.log("Content for createToken", content);
return (
typeof content.name === "string" &&
typeof content.uri === "string" &&
typeof content.symbol === "string" &&
typeof content.decimals === "number" &&
typeof content.initialSupply === "number"
);
}

const createTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined.

Example response:
\`\`\`json
{
"name": "Example Token",
"symbol": "EXMPL",
"uri": "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/CompressedCoil/image.png",
"decimals": 18,
"initialSupply": 1000000,
}
\`\`\`

{{recentMessages}}

Given the recent messages, extract the following information about the requested token transfer:
- Token name
- Token symbol
- Token uri
- Token decimals
- Token initialSupply

Respond with a JSON markdown block containing only the extracted values.`;

export default {
name: "CREATE_TOKEN",
similes: ["DEPLOY_TOKEN"],
validate: async (runtime: IAgentRuntime, message: Memory) => true,
description: "Create tokens",
handler: async (
runtime: IAgentRuntime,
message: Memory,
state: State,
_options: { [key: string]: unknown },
callback?: HandlerCallback
): Promise<boolean> => {
elizaLogger.log("Starting CREATE_TOKEN handler...");
// Initialize or update state
if (!state) {
state = (await runtime.composeState(message)) as State;
} else {
state = await runtime.updateRecentMessageState(state);
}

// Compose transfer context
const transferContext = composeContext({
state,
template: createTemplate,
});

// Generate transfer content
const content = await generateObjectDeprecated({
runtime,
context: transferContext,
modelClass: ModelClass.LARGE,
});

// Validate transfer content
if (!isCreateTokenContent(content)) {
elizaLogger.error("Invalid content for CREATE_TOKEN action.");
if (callback) {
callback({
text: "Unable to process create token request. Invalid content provided.",
content: { error: "Invalid creat token content" },
});
}
return false;
}

elizaLogger.log("Init solana agent kit...");
const solanaPrivatekey = runtime.getSetting("SOLANA_PRIVATE_KEY");
const rpc = runtime.getSetting("RPC_URL");
const openAIKey = runtime.getSetting("OPENAI_API_KEY");
const solanaAgentKit = new SolanaAgentKit(
solanaPrivatekey,
rpc,
openAIKey
);
try {
const deployedAddress = await solanaAgentKit.deployToken(
content.name,
content.uri,
content.symbol,
content.decimals
// content.initialSupply comment out this cause the sdk has some issue with this parameter
);
elizaLogger.log("Create successful: ", deployedAddress);
elizaLogger.log(deployedAddress);
if (callback) {
callback({
text: `Successfully create token ${content.name}`,
content: {
success: true,
deployedAddress,
},
});
}
return true;
} catch (error) {
if (callback) {
elizaLogger.error("Error during create token: ", error);
callback({
text: `Error creating token: ${error.message}`,
content: { error: error.message },
});
}
return false;
}
},
examples: [
[
{
user: "{{user1}}",
content: {
text: "Create token, name is Example Token, symbol is EXMPL, uri is https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/CompressedCoil/image.png, decimals is 9, initialSupply is 100000000000",
},
},
{
user: "{{user2}}",
content: {
text: "I'll create token now...",
action: "CREATE_TOKEN",
},
},
{
user: "{{user2}}",
content: {
text: "Successfully create token 9jW8FPr6BSSsemWPV22UUCzSqkVdTp6HTyPqeqyuBbCa",
},
},
],
] as ActionExample[][],
} as Action;
12 changes: 12 additions & 0 deletions packages/plugin-solana-agentkit/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Plugin } from "@elizaos/core";
import createToken from "./actions/createToken.ts";

export const solanaAgentkitPlguin: Plugin = {
name: "solana",
description: "Solana Plugin with solana agent kit for Eliza",
actions: [createToken],
evaluators: [],
providers: [],
};

export default solanaAgentkitPlguin;
10 changes: 10 additions & 0 deletions packages/plugin-solana-agentkit/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../core/tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
},
"include": [
"src/**/*.ts"
]
}
29 changes: 29 additions & 0 deletions packages/plugin-solana-agentkit/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { defineConfig } from "tsup";

export default defineConfig({
entry: ["src/index.ts"],
outDir: "dist",
sourcemap: true,
clean: true,
format: ["esm"], // Ensure you're targeting CommonJS
external: [
"dotenv", // Externalize dotenv to prevent bundling
"fs", // Externalize fs to use Node.js built-in module
"path", // Externalize other built-ins if necessary
"@reflink/reflink",
"@node-llama-cpp",
"https",
"http",
"agentkeepalive",
"safe-buffer",
"base-x",
"bs58",
"borsh",
"@solana/buffer-layout",
"stream",
"buffer",
"querystring",
"amqplib",
// Add other modules you want to externalize
],
});
Loading
Loading