From bc815f748ada42e462a466242934e08ffd39b623 Mon Sep 17 00:00:00 2001 From: Piotr Ostrowski Date: Wed, 5 Feb 2025 21:36:16 -0800 Subject: [PATCH] massive cleanup --- listen-kit/Cargo.toml | 5 +- listen-kit/examples/solana_agent.rs | 8 +- listen-kit/src/agent.rs | 127 ---------------------- listen-kit/src/bin/server.rs | 22 +--- listen-kit/src/common.rs | 17 +++ listen-kit/src/cross_chain/lifi/tokens.rs | 2 +- listen-kit/src/evm/agent.rs | 27 +++++ listen-kit/src/evm/mod.rs | 1 + listen-kit/src/http/routes.rs | 2 - listen-kit/src/http/server.rs | 5 +- listen-kit/src/http/state.rs | 19 ---- listen-kit/src/lib.rs | 6 +- listen-kit/src/signer/mod.rs | 12 +- listen-kit/src/signer/privy.rs | 1 - listen-kit/src/solana/agent.rs | 34 ++++++ listen-kit/src/solana/mod.rs | 1 + listen-kit/src/wallet_manager/mod.rs | 25 +---- 17 files changed, 108 insertions(+), 206 deletions(-) delete mode 100644 listen-kit/src/agent.rs create mode 100644 listen-kit/src/evm/agent.rs create mode 100644 listen-kit/src/solana/agent.rs diff --git a/listen-kit/Cargo.toml b/listen-kit/Cargo.toml index e5a7d23..0520592 100644 --- a/listen-kit/Cargo.toml +++ b/listen-kit/Cargo.toml @@ -7,14 +7,13 @@ description = "Blockchain actions for AI agents" documentation = "https://docs.listen-rs.com" [features] -default = ["full"] +default = ["http"] full = ["http", "solana", "evm"] http = [ "solana", "actix-web", "actix-cors", "actix-web-lab", - "futures-util", "tokio-stream", "jsonwebtoken", "redis", @@ -56,6 +55,7 @@ futures = "0.3.31" serde_with = "3.12.0" async-trait = "0.1.85" ctor = "0.2.0" +futures-util = { version = "0.3" } # evm alloy = { version = "0.9", features = ["full"], optional = true } @@ -77,7 +77,6 @@ spl-associated-token-account = { version = "6.0.0", optional = true } actix-web = { version = "4", optional = true } actix-cors = { version = "0.6", optional = true } actix-web-lab = { version = "0.20", optional = true } -futures-util = { version = "0.3", optional = true } tokio-stream = { version = "0.1.17", optional = true } jsonwebtoken = { version = "9.3.0", optional = true } redis = { version = "0.28.2", features = ["tokio-comp"], optional = true } diff --git a/listen-kit/examples/solana_agent.rs b/listen-kit/examples/solana_agent.rs index 73ee4e6..a1ff4eb 100644 --- a/listen-kit/examples/solana_agent.rs +++ b/listen-kit/examples/solana_agent.rs @@ -1,10 +1,10 @@ #[cfg(feature = "solana")] use { - anyhow::Result, listen_kit::agent::create_solana_agent, - listen_kit::reasoning_loop::ReasoningLoop, + anyhow::Result, listen_kit::reasoning_loop::ReasoningLoop, listen_kit::signer::solana::LocalSolanaSigner, - listen_kit::signer::SignerContext, listen_kit::solana::util::env, - rig::completion::Message, std::sync::Arc, + listen_kit::signer::SignerContext, + listen_kit::solana::agent::create_solana_agent, + listen_kit::solana::util::env, rig::completion::Message, std::sync::Arc, }; #[cfg(feature = "solana")] diff --git a/listen-kit/src/agent.rs b/listen-kit/src/agent.rs deleted file mode 100644 index 38da6cc..0000000 --- a/listen-kit/src/agent.rs +++ /dev/null @@ -1,127 +0,0 @@ -use anyhow::Result; -use rig::agent::{Agent, AgentBuilder}; -use rig::providers::anthropic::completion::CompletionModel as AnthropicCompletionModel; - -const PREAMBLE_COMMON: &str = ""; - -#[cfg(feature = "evm")] -use crate::evm::tools::{ - ApproveTokenForRouterSpend, GetErc20Balance, GetEthBalance, Trade, - TransferErc20, TransferEth, VerifySwapRouterHasAllowance, WalletAddress, -}; -#[cfg(feature = "solana")] -use crate::solana::tools::{ - BuyPumpFunToken, DeployPumpFunToken, FetchTokenPrice, GetPortfolio, - GetPublicKey, GetSolBalance, GetSplTokenBalance, PerformJupiterSwap, - SearchOnDexScreener, SellPumpFunToken, TransferSol, TransferSplToken, -}; - -// this might need some refactoring, as truly, with http -// and remote signing you can get away without much of the core deps, both evm+solana -#[cfg(feature = "full")] -use crate::cross_chain::tools::{GetMultichainQuote, MultichainSwap}; - -pub fn claude_agent_builder() -> AgentBuilder { - rig::providers::anthropic::Client::from_env() - .agent(rig::providers::anthropic::CLAUDE_3_5_SONNET) -} - -pub async fn plain_agent() -> Result> { - Ok(claude_agent_builder() - .preamble("be nice to the users") - .max_tokens(1024) - .build()) -} - -#[cfg(feature = "solana")] -pub async fn create_solana_agent() -> Result> -{ - Ok(claude_agent_builder() - .preamble(&format!( - "{} {}", - "you are a solana trading agent;", PREAMBLE_COMMON - )) - .max_tokens(1024) - .tool(PerformJupiterSwap) - .tool(TransferSol) - .tool(TransferSplToken) - .tool(GetPublicKey) - .tool(GetSolBalance) - .tool(GetSplTokenBalance) - .tool(FetchTokenPrice) - .tool(GetPortfolio) - .tool(SearchOnDexScreener) - .build()) -} - -#[cfg(feature = "solana")] -pub async fn create_pump_agent() -> Result> { - Ok(claude_agent_builder() - .preamble(&format!( - "{} {}", - "you are a pump.fun trading agent", PREAMBLE_COMMON, - )) - .max_tokens(1024) - .tool(TransferSol) - .tool(TransferSplToken) - .tool(GetPublicKey) - .tool(GetSolBalance) - .tool(GetSplTokenBalance) - .tool(DeployPumpFunToken) - .tool(BuyPumpFunToken) - .tool(SellPumpFunToken) - .tool(GetPortfolio) - .build()) -} - -#[cfg(feature = "evm")] -pub async fn create_evm_agent() -> Result> { - Ok(claude_agent_builder() - .preamble(&format!( - "{} {}", - "you are an ethereum trading agent", PREAMBLE_COMMON - )) - .max_tokens(1024) - .tool(Trade) - .tool(TransferEth) - .tool(TransferErc20) - .tool(WalletAddress) - .tool(GetEthBalance) - .tool(GetErc20Balance) - .tool(ApproveTokenForRouterSpend) - .tool(VerifySwapRouterHasAllowance) - .build()) -} - -#[cfg(feature = "full")] -pub async fn create_multichain_agent( -) -> Result> { - // note: this is only going to work with a signer that implements both evm and solana - Ok(claude_agent_builder() - .preamble(&format!( - "{} {}", - "you are a an agent with tools for trading on solana and ethereum", PREAMBLE_COMMON, - )) - .max_tokens(1024) - .tool(GetMultichainQuote) - .tool(MultichainSwap) - .tool(GetSolBalance) - .tool(GetEthBalance) - .tool(GetErc20Balance) - .tool(ApproveTokenForRouterSpend) - .tool(VerifySwapRouterHasAllowance) - .tool(TransferSol) - .tool(TransferSplToken) - .tool(GetPublicKey) - .tool(GetSolBalance) - .tool(GetSplTokenBalance) - .tool(DeployPumpFunToken) - .tool(BuyPumpFunToken) - .tool(SellPumpFunToken) - .tool(GetPortfolio) - .tool(GetMultichainQuote) - .tool(MultichainSwap) - .tool(PerformJupiterSwap) - .tool(SearchOnDexScreener) - .build()) -} diff --git a/listen-kit/src/bin/server.rs b/listen-kit/src/bin/server.rs index 7e1573e..38d6440 100644 --- a/listen-kit/src/bin/server.rs +++ b/listen-kit/src/bin/server.rs @@ -4,9 +4,6 @@ use listen_kit::http::server::run_server; #[cfg(feature = "http")] #[actix_web::main] async fn main() -> std::io::Result<()> { - use listen_kit::agent::{ - create_evm_agent, create_pump_agent, create_solana_agent, - }; use listen_kit::wallet_manager::config::PrivyConfig; use listen_kit::wallet_manager::WalletManager; @@ -18,32 +15,21 @@ async fn main() -> std::io::Result<()> { // Create agents based on enabled features #[cfg(feature = "solana")] - let solana_agent = create_solana_agent() - .await - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; - - #[cfg(feature = "solana")] - let pump_fun_agent = create_pump_agent() + let solana_agent = listen_kit::solana::agent::create_solana_agent() .await .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; #[cfg(feature = "evm")] - let evm_agent = create_evm_agent() + let evm_agent = listen_kit::evm::agent::create_evm_agent() .await .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; // Run server with appropriate agents based on features #[cfg(all(feature = "solana", feature = "evm"))] - return run_server( - solana_agent, - pump_fun_agent, - evm_agent, - wallet_manager, - ) - .await; + return run_server(solana_agent, evm_agent, wallet_manager).await; #[cfg(all(feature = "solana", not(feature = "evm")))] - return run_server(solana_agent, pump_fun_agent, wallet_manager).await; + return run_server(solana_agent, wallet_manager).await; #[cfg(all(feature = "evm", not(feature = "solana")))] return run_server(evm_agent, wallet_manager).await; diff --git a/listen-kit/src/common.rs b/listen-kit/src/common.rs index 2d1c9c0..386d670 100644 --- a/listen-kit/src/common.rs +++ b/listen-kit/src/common.rs @@ -34,3 +34,20 @@ where SignerContext::with_signer(signer, async { f().await }).await }) } + +use rig::agent::{Agent, AgentBuilder}; +use rig::providers::anthropic::completion::CompletionModel as AnthropicCompletionModel; + +pub fn claude_agent_builder() -> AgentBuilder { + rig::providers::anthropic::Client::from_env() + .agent(rig::providers::anthropic::CLAUDE_3_5_SONNET) +} + +pub async fn plain_agent() -> Result> { + Ok(claude_agent_builder() + .preamble("be nice to the users") + .max_tokens(1024) + .build()) +} + +pub const PREAMBLE_COMMON: &str = ""; diff --git a/listen-kit/src/cross_chain/lifi/tokens.rs b/listen-kit/src/cross_chain/lifi/tokens.rs index 9278aff..11eef36 100644 --- a/listen-kit/src/cross_chain/lifi/tokens.rs +++ b/listen-kit/src/cross_chain/lifi/tokens.rs @@ -1,6 +1,6 @@ -use alloy::primitives::map::HashMap; use serde::{Deserialize, Serialize}; use serde_json::Number; +use std::collections::HashMap; #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] diff --git a/listen-kit/src/evm/agent.rs b/listen-kit/src/evm/agent.rs new file mode 100644 index 0000000..61511b2 --- /dev/null +++ b/listen-kit/src/evm/agent.rs @@ -0,0 +1,27 @@ +use anyhow::Result; +use rig::agent::Agent; +use rig::providers::anthropic::completion::CompletionModel as AnthropicCompletionModel; + +use super::tools::{ + ApproveTokenForRouterSpend, GetErc20Balance, GetEthBalance, Trade, + TransferErc20, TransferEth, VerifySwapRouterHasAllowance, WalletAddress, +}; +use crate::common::{claude_agent_builder, PREAMBLE_COMMON}; + +pub async fn create_evm_agent() -> Result> { + Ok(claude_agent_builder() + .preamble(&format!( + "{} {}", + "you are an ethereum trading agent", PREAMBLE_COMMON + )) + .max_tokens(1024) + .tool(Trade) + .tool(TransferEth) + .tool(TransferErc20) + .tool(WalletAddress) + .tool(GetEthBalance) + .tool(GetErc20Balance) + .tool(ApproveTokenForRouterSpend) + .tool(VerifySwapRouterHasAllowance) + .build()) +} diff --git a/listen-kit/src/evm/mod.rs b/listen-kit/src/evm/mod.rs index d917032..8b3931c 100644 --- a/listen-kit/src/evm/mod.rs +++ b/listen-kit/src/evm/mod.rs @@ -1,4 +1,5 @@ pub mod abi; +pub mod agent; pub mod balance; pub mod data; pub mod price; diff --git a/listen-kit/src/http/routes.rs b/listen-kit/src/http/routes.rs index ffb79e2..9d54df6 100644 --- a/listen-kit/src/http/routes.rs +++ b/listen-kit/src/http/routes.rs @@ -66,8 +66,6 @@ async fn stream( let agent = match request.chain.as_deref() { #[cfg(feature = "solana")] Some("solana") => state.solana_agent.clone(), - #[cfg(feature = "solana")] - Some("pump") => state.pump_fun_agent.clone(), #[cfg(feature = "evm")] Some("evm") => state.evm_agent.clone(), Some(chain) => { diff --git a/listen-kit/src/http/server.rs b/listen-kit/src/http/server.rs index aec51b9..e5d33ed 100644 --- a/listen-kit/src/http/server.rs +++ b/listen-kit/src/http/server.rs @@ -10,7 +10,6 @@ use super::state::AppState; pub async fn run_server( #[cfg(feature = "solana")] solana_agent: Agent, - #[cfg(feature = "solana")] pump_fun_agent: Agent, #[cfg(feature = "evm")] evm_agent: Agent, wallet_manager: WalletManager, ) -> std::io::Result<()> { @@ -18,9 +17,7 @@ pub async fn run_server( #[cfg(feature = "solana")] { - builder = builder - .with_solana_agent(solana_agent) - .with_pump_fun_agent(pump_fun_agent); + builder = builder.with_solana_agent(solana_agent); } #[cfg(feature = "evm")] diff --git a/listen-kit/src/http/state.rs b/listen-kit/src/http/state.rs index 00d85e3..93f7a09 100644 --- a/listen-kit/src/http/state.rs +++ b/listen-kit/src/http/state.rs @@ -6,8 +6,6 @@ use std::sync::Arc; pub struct AppState { #[cfg(feature = "solana")] pub(crate) solana_agent: Arc>, - #[cfg(feature = "solana")] - pub(crate) pump_fun_agent: Arc>, #[cfg(feature = "evm")] pub(crate) evm_agent: Arc>, pub(crate) wallet_manager: Arc, @@ -16,8 +14,6 @@ pub struct AppState { pub struct AppStateBuilder { #[cfg(feature = "solana")] solana_agent: Option>, - #[cfg(feature = "solana")] - pump_fun_agent: Option>, #[cfg(feature = "evm")] evm_agent: Option>, wallet_manager: Option, @@ -34,8 +30,6 @@ impl AppStateBuilder { Self { #[cfg(feature = "solana")] solana_agent: None, - #[cfg(feature = "solana")] - pump_fun_agent: None, #[cfg(feature = "evm")] evm_agent: None, wallet_manager: None, @@ -51,15 +45,6 @@ impl AppStateBuilder { self } - #[cfg(feature = "solana")] - pub fn with_pump_fun_agent( - mut self, - agent: Agent, - ) -> Self { - self.pump_fun_agent = Some(agent); - self - } - #[cfg(feature = "evm")] pub fn with_evm_agent(mut self, agent: Agent) -> Self { self.evm_agent = Some(agent); @@ -80,10 +65,6 @@ impl AppStateBuilder { solana_agent: Arc::new(self.solana_agent.ok_or( "Solana agent is required when solana feature is enabled", )?), - #[cfg(feature = "solana")] - pump_fun_agent: Arc::new(self.pump_fun_agent.ok_or( - "Pump fun agent is required when solana feature is enabled", - )?), #[cfg(feature = "evm")] evm_agent: Arc::new(self.evm_agent.ok_or( "EVM agent is required when evm feature is enabled", diff --git a/listen-kit/src/lib.rs b/listen-kit/src/lib.rs index d42c689..6093c16 100644 --- a/listen-kit/src/lib.rs +++ b/listen-kit/src/lib.rs @@ -10,12 +10,8 @@ pub mod evm; #[cfg(feature = "http")] pub mod wallet_manager; -// this might not have to be feature full, if privy is not -#[cfg(feature = "full")] -pub mod cross_chain; - -pub mod agent; pub mod common; +pub mod cross_chain; pub mod reasoning_loop; pub mod signer; diff --git a/listen-kit/src/signer/mod.rs b/listen-kit/src/signer/mod.rs index 2245fc0..612af58 100644 --- a/listen-kit/src/signer/mod.rs +++ b/listen-kit/src/signer/mod.rs @@ -36,12 +36,10 @@ pub enum SignerType { #[async_trait] pub trait TransactionSigner: Send + Sync { - #[cfg(feature = "evm")] fn address(&self) -> String { unimplemented!() } - #[cfg(feature = "solana")] fn pubkey(&self) -> String { unimplemented!() } @@ -66,7 +64,6 @@ pub trait TransactionSigner: Send + Sync { )) } - #[cfg(feature = "solana")] async fn sign_and_send_encoded_solana_transaction( &self, _tx: String, @@ -75,6 +72,15 @@ pub trait TransactionSigner: Send + Sync { "Solana transactions not supported by this signer" )) } + + async fn sign_and_send_encoded_evm_transaction( + &self, + _tx: String, + ) -> Result { + Err(anyhow::anyhow!( + "EVM transactions not supported by this signer" + )) + } } tokio::task_local! { diff --git a/listen-kit/src/signer/privy.rs b/listen-kit/src/signer/privy.rs index f0b4177..82462da 100644 --- a/listen-kit/src/signer/privy.rs +++ b/listen-kit/src/signer/privy.rs @@ -59,7 +59,6 @@ impl TransactionSigner for PrivySigner { Ok(tx_hash) } - #[cfg(feature = "solana")] async fn sign_and_send_encoded_solana_transaction( &self, encoded_transaction: String, diff --git a/listen-kit/src/solana/agent.rs b/listen-kit/src/solana/agent.rs new file mode 100644 index 0000000..52041f0 --- /dev/null +++ b/listen-kit/src/solana/agent.rs @@ -0,0 +1,34 @@ +use anyhow::Result; +use rig::agent::Agent; +use rig::providers::anthropic::completion::CompletionModel as AnthropicCompletionModel; + +use super::tools::{ + BuyPumpFunToken, DeployPumpFunToken, FetchTokenPrice, GetPortfolio, + GetPublicKey, GetSolBalance, GetSplTokenBalance, PerformJupiterSwap, + SearchOnDexScreener, SellPumpFunToken, TransferSol, TransferSplToken, +}; +use crate::common::{claude_agent_builder, PREAMBLE_COMMON}; + +pub async fn create_solana_agent() -> Result> +{ + Ok(claude_agent_builder() + .preamble(&format!( + "{} {}", + "you are a solana trading agent that can also interact with pump.fun;", + PREAMBLE_COMMON + )) + .max_tokens(1024) + .tool(PerformJupiterSwap) + .tool(TransferSol) + .tool(TransferSplToken) + .tool(GetPublicKey) + .tool(GetSolBalance) + .tool(GetSplTokenBalance) + .tool(FetchTokenPrice) + .tool(GetPortfolio) + .tool(SearchOnDexScreener) + .tool(DeployPumpFunToken) + .tool(BuyPumpFunToken) + .tool(SellPumpFunToken) + .build()) +} diff --git a/listen-kit/src/solana/mod.rs b/listen-kit/src/solana/mod.rs index e8ec3dc..7b1249e 100644 --- a/listen-kit/src/solana/mod.rs +++ b/listen-kit/src/solana/mod.rs @@ -1,3 +1,4 @@ +pub mod agent; pub mod balance; pub mod blockhash; pub mod constants; diff --git a/listen-kit/src/wallet_manager/mod.rs b/listen-kit/src/wallet_manager/mod.rs index 5ec4cd8..bb9ada2 100644 --- a/listen-kit/src/wallet_manager/mod.rs +++ b/listen-kit/src/wallet_manager/mod.rs @@ -25,9 +25,7 @@ pub struct WalletManager { pub struct UserSession { pub(crate) user_id: String, pub(crate) session_id: String, - #[cfg(feature = "evm")] pub(crate) wallet_address: String, - #[cfg(feature = "solana")] pub(crate) pubkey: String, } @@ -74,27 +72,17 @@ impl WalletManager { let mut session = UserSession { user_id: user.id, session_id: claims.session_id, - #[cfg(feature = "evm")] wallet_address: String::new(), - #[cfg(feature = "solana")] pubkey: String::new(), }; - // Handle Solana wallet - #[cfg(feature = "solana")] - { - let solana_wallet = - find_wallet(&user.linked_accounts, "solana", "privy")?; - session.pubkey = solana_wallet.address.clone(); - } + let solana_wallet = + find_wallet(&user.linked_accounts, "solana", "privy")?; + session.pubkey = solana_wallet.address.clone(); - // Handle EVM wallet - #[cfg(feature = "evm")] - { - let evm_wallet = - find_wallet(&user.linked_accounts, "ethereum", "privy")?; - session.wallet_address = evm_wallet.address.clone(); - } + let evm_wallet = + find_wallet(&user.linked_accounts, "ethereum", "privy")?; + session.wallet_address = evm_wallet.address.clone(); Ok(session) } @@ -150,7 +138,6 @@ impl WalletManager { .await } - #[cfg(feature = "solana")] pub async fn sign_and_send_encoded_solana_transaction( &self, address: String,