mirror of
https://github.com/d0zingcat/solana-agent-kit.git
synced 2026-05-14 15:10:20 +00:00
219 lines
6.1 KiB
TypeScript
219 lines
6.1 KiB
TypeScript
import { SolanaAgentKit } from "../src";
|
|
import { createSolanaTools } from "../src/langchain";
|
|
import { HumanMessage } from "@langchain/core/messages";
|
|
import { MemorySaver } from "@langchain/langgraph";
|
|
import { createReactAgent } from "@langchain/langgraph/prebuilt";
|
|
import { ChatOpenAI } from "@langchain/openai";
|
|
import * as dotenv from "dotenv";
|
|
import * as fs from "fs";
|
|
import * as readline from "readline";
|
|
|
|
dotenv.config();
|
|
|
|
function validateEnvironment(): void {
|
|
const missingVars: string[] = [];
|
|
const requiredVars = ["OPENAI_API_KEY", "RPC_URL", "SOLANA_PRIVATE_KEY"];
|
|
|
|
requiredVars.forEach((varName) => {
|
|
if (!process.env[varName]) {
|
|
missingVars.push(varName);
|
|
}
|
|
});
|
|
|
|
if (missingVars.length > 0) {
|
|
console.error("Error: Required environment variables are not set");
|
|
missingVars.forEach((varName) => {
|
|
console.error(`${varName}=your_${varName.toLowerCase()}_here`);
|
|
});
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
validateEnvironment();
|
|
|
|
const WALLET_DATA_FILE = "wallet_data.txt";
|
|
|
|
async function initializeAgent() {
|
|
try {
|
|
const llm = new ChatOpenAI({
|
|
modelName: "gpt-4o-mini",
|
|
temperature: 0.7,
|
|
});
|
|
|
|
let walletDataStr: string | null = null;
|
|
|
|
if (fs.existsSync(WALLET_DATA_FILE)) {
|
|
try {
|
|
walletDataStr = fs.readFileSync(WALLET_DATA_FILE, "utf8");
|
|
} catch (error) {
|
|
console.error("Error reading wallet data:", error);
|
|
}
|
|
}
|
|
|
|
const solanaAgent = new SolanaAgentKit(
|
|
process.env.SOLANA_PRIVATE_KEY!,
|
|
process.env.RPC_URL,
|
|
process.env.OPENAI_API_KEY!,
|
|
);
|
|
|
|
const tools = createSolanaTools(solanaAgent);
|
|
const memory = new MemorySaver();
|
|
const config = { configurable: { thread_id: "Solana Agent Kit!" } };
|
|
|
|
const agent = createReactAgent({
|
|
llm,
|
|
tools,
|
|
checkpointSaver: memory,
|
|
messageModifier: `
|
|
You are a helpful agent that can interact onchain using the Solana Agent Kit. You are
|
|
empowered to interact onchain using your tools. If you ever need funds, you can request them from the
|
|
faucet. If not, you can provide your wallet details and request funds from the user. If there is a 5XX
|
|
(internal) HTTP error code, ask the user to try again later. If someone asks you to do something you
|
|
can't do with your currently available tools, you must say so, and encourage them to implement it
|
|
themselves using the Solana Agent Kit, recommend they go to https://www.solanaagentkit.xyz for more information. Be
|
|
concise and helpful with your responses. Refrain from restating your tools' descriptions unless it is explicitly requested.
|
|
`,
|
|
});
|
|
|
|
if (walletDataStr) {
|
|
fs.writeFileSync(WALLET_DATA_FILE, walletDataStr);
|
|
}
|
|
|
|
return { agent, config };
|
|
} catch (error) {
|
|
console.error("Failed to initialize agent:", error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async function runAutonomousMode(agent: any, config: any, interval = 10) {
|
|
console.log("Starting autonomous mode...");
|
|
|
|
while (true) {
|
|
try {
|
|
const thought =
|
|
"Be creative and do something interesting on the blockchain. " +
|
|
"Choose an action or set of actions and execute it that highlights your abilities.";
|
|
|
|
const stream = await agent.stream(
|
|
{ messages: [new HumanMessage(thought)] },
|
|
config,
|
|
);
|
|
|
|
for await (const chunk of stream) {
|
|
if ("agent" in chunk) {
|
|
console.log(chunk.agent.messages[0].content);
|
|
} else if ("tools" in chunk) {
|
|
console.log(chunk.tools.messages[0].content);
|
|
}
|
|
console.log("-------------------");
|
|
}
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, interval * 1000));
|
|
} catch (error) {
|
|
if (error instanceof Error) {
|
|
console.error("Error:", error.message);
|
|
}
|
|
process.exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
async function runChatMode(agent: any, config: any) {
|
|
console.log("Starting chat mode... Type 'exit' to end.");
|
|
|
|
const rl = readline.createInterface({
|
|
input: process.stdin,
|
|
output: process.stdout,
|
|
});
|
|
|
|
const question = (prompt: string): Promise<string> =>
|
|
new Promise((resolve) => rl.question(prompt, resolve));
|
|
|
|
try {
|
|
while (true) {
|
|
const userInput = await question("\nPrompt: ");
|
|
|
|
if (userInput.toLowerCase() === "exit") {
|
|
break;
|
|
}
|
|
|
|
const stream = await agent.stream(
|
|
{ messages: [new HumanMessage(userInput)] },
|
|
config,
|
|
);
|
|
|
|
for await (const chunk of stream) {
|
|
if ("agent" in chunk) {
|
|
console.log(chunk.agent.messages[0].content);
|
|
} else if ("tools" in chunk) {
|
|
console.log(chunk.tools.messages[0].content);
|
|
}
|
|
console.log("-------------------");
|
|
}
|
|
}
|
|
} catch (error) {
|
|
if (error instanceof Error) {
|
|
console.error("Error:", error.message);
|
|
}
|
|
process.exit(1);
|
|
} finally {
|
|
rl.close();
|
|
}
|
|
}
|
|
|
|
async function chooseMode(): Promise<"chat" | "auto"> {
|
|
const rl = readline.createInterface({
|
|
input: process.stdin,
|
|
output: process.stdout,
|
|
});
|
|
|
|
const question = (prompt: string): Promise<string> =>
|
|
new Promise((resolve) => rl.question(prompt, resolve));
|
|
|
|
while (true) {
|
|
console.log("\nAvailable modes:");
|
|
console.log("1. chat - Interactive chat mode");
|
|
console.log("2. auto - Autonomous action mode");
|
|
|
|
const choice = (await question("\nChoose a mode (enter number or name): "))
|
|
.toLowerCase()
|
|
.trim();
|
|
|
|
rl.close();
|
|
|
|
if (choice === "1" || choice === "chat") {
|
|
return "chat";
|
|
} else if (choice === "2" || choice === "auto") {
|
|
return "auto";
|
|
}
|
|
console.log("Invalid choice. Please try again.");
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
try {
|
|
console.log("Starting Agent...");
|
|
const { agent, config } = await initializeAgent();
|
|
const mode = await chooseMode();
|
|
|
|
if (mode === "chat") {
|
|
await runChatMode(agent, config);
|
|
} else {
|
|
await runAutonomousMode(agent, config);
|
|
}
|
|
} catch (error) {
|
|
if (error instanceof Error) {
|
|
console.error("Error:", error.message);
|
|
}
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
if (require.main === module) {
|
|
main().catch((error) => {
|
|
console.error("Fatal error:", error);
|
|
process.exit(1);
|
|
});
|
|
}
|