edwin-sdk
Version:
SDK for integrating AI agents with DeFi protocols
141 lines (116 loc) • 4.49 kB
text/typescript
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 readline from 'readline';
import { Edwin, EdwinConfig } from '../../src/client';
import { getLangchainToolsFromEdwin } from '../../src/adapters/langchain';
dotenv.config();
function validateEnvironment(): void {
const missingVars: string[] = [];
const requiredVars = ['OPENAI_API_KEY', 'EVM_PRIVATE_KEY', '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();
async function initializeAgent() {
try {
const llm = new ChatOpenAI({
modelName: 'gpt-4o-mini',
temperature: 0.7,
});
if (!process.env.EVM_PRIVATE_KEY) {
console.error('Error: EVM private key is not set');
throw new Error('EVM private key is not set');
}
const plugins = ['meteora', 'aave'];
console.log('Used plugins:', plugins);
// Configure Edwin wallets and providers
const edwinConfig: EdwinConfig = {
evmPrivateKey: process.env.EVM_PRIVATE_KEY as `0x${string}`,
solanaPrivateKey: process.env.SOLANA_PRIVATE_KEY,
plugins: plugins,
};
// Initialize Edwin SDK
const edwin = new Edwin(edwinConfig);
const tools = await getLangchainToolsFromEdwin({ edwin });
const memory = new MemorySaver();
const config = { configurable: { thread_id: 'Edwin SDK Usage' } };
const agent = createReactAgent({
llm,
tools,
checkpointSaver: memory,
messageModifier: `
- You are an agent that can interact on-chain evm and solana using the tools of Edwin SDK
- If the tool requires fund, you can response to require fund depositing
- If there is any errors, ask the user to try it again
- If the user asks you to do something that you can't do, you must say so and encourage them to implement it themselves using the Edwin SDK and visit https://edwin.finance/ for more information
- Be concise and helpful with your responses`,
});
return { agent, config };
} catch (error) {
console.error('Failed to initialize agent:', error);
throw error;
}
}
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 main() {
try {
console.log('Starting Agent...');
const { agent, config } = await initializeAgent();
await runChatMode(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);
});
}