actor.rs
1 /// Bot actor trait and types 2 /// 3 /// Defines the core Bot trait that all bot implementations must follow. 4 /// Uses async trait for lifecycle methods: setup, execute, teardown. 5 6 use crate::{ExecutionContext, Identity, Wallet, Result}; 7 use async_trait::async_trait; 8 use serde::{Deserialize, Serialize}; 9 use std::sync::Arc; 10 use parking_lot::RwLock; 11 12 /// Context provided to bots during their lifecycle 13 #[derive(Debug, Clone)] 14 pub struct BotContext { 15 pub execution: ExecutionContext, 16 pub identity: Identity, 17 pub wallet: Arc<RwLock<Wallet>>, 18 } 19 20 impl BotContext { 21 pub fn new(execution: ExecutionContext, identity: Identity, wallet: Wallet) -> Self { 22 Self { 23 execution, 24 identity, 25 wallet: Arc::new(RwLock::new(wallet)), 26 } 27 } 28 } 29 30 /// Result of a behavior execution 31 #[derive(Debug, Clone, Serialize, Deserialize)] 32 pub struct BehaviorResult { 33 /// Whether the behavior succeeded 34 pub success: bool, 35 36 /// Human-readable message 37 pub message: String, 38 39 /// Structured data (e.g., transaction hashes, block numbers) 40 pub data: serde_json::Value, 41 42 /// Performance metrics 43 pub metrics: BehaviorMetrics, 44 } 45 46 #[derive(Debug, Clone, Serialize, Deserialize)] 47 pub struct BehaviorMetrics { 48 /// Duration in milliseconds 49 pub duration_ms: u64, 50 51 /// Number of operations performed 52 pub operations_count: u64, 53 54 /// Number of errors encountered 55 pub errors_count: u64, 56 } 57 58 impl BehaviorResult { 59 pub fn success(message: impl Into<String>) -> Self { 60 Self { 61 success: true, 62 message: message.into(), 63 data: serde_json::Value::Null, 64 metrics: BehaviorMetrics { 65 duration_ms: 0, 66 operations_count: 1, 67 errors_count: 0, 68 }, 69 } 70 } 71 72 pub fn error(message: impl Into<String>) -> Self { 73 Self { 74 success: false, 75 message: message.into(), 76 data: serde_json::Value::Null, 77 metrics: BehaviorMetrics { 78 duration_ms: 0, 79 operations_count: 0, 80 errors_count: 1, 81 }, 82 } 83 } 84 85 pub fn with_data(mut self, data: serde_json::Value) -> Self { 86 self.data = data; 87 self 88 } 89 90 pub fn with_metrics(mut self, metrics: BehaviorMetrics) -> Self { 91 self.metrics = metrics; 92 self 93 } 94 } 95 96 /// Core Bot trait that all bot implementations must follow 97 /// 98 /// Bots have a three-phase lifecycle: 99 /// 1. setup() - Initialize state, register with network 100 /// 2. execute_behavior() - Perform the bot's intended actions 101 /// 3. teardown() - Clean up resources, unregister 102 #[async_trait] 103 pub trait Bot: Send + Sync { 104 /// Initialize the bot 105 /// 106 /// This is called once when the bot is spawned. Use this to: 107 /// - Establish network connections 108 /// - Register with services 109 /// - Load initial state 110 /// 111 /// # Errors 112 /// Returns an error if initialization fails 113 async fn setup(&mut self, context: &BotContext) -> Result<()>; 114 115 /// Execute a behavior pattern 116 /// 117 /// This is the main action method. It executes a specific behavior 118 /// pattern identified by behavior_id. 119 /// 120 /// # Arguments 121 /// - `behavior_id`: Identifier of the behavior to execute 122 /// 123 /// # Errors 124 /// Returns an error if behavior execution fails 125 async fn execute_behavior(&mut self, behavior_id: &str) -> Result<BehaviorResult>; 126 127 /// Clean up the bot 128 /// 129 /// This is called when the bot is stopped. Use this to: 130 /// - Close network connections 131 /// - Unregister from services 132 /// - Flush pending operations 133 /// 134 /// # Errors 135 /// Returns an error if teardown fails 136 async fn teardown(&mut self) -> Result<()>; 137 138 /// Get the bot's unique identifier 139 fn id(&self) -> &str; 140 141 /// Get the bot's role 142 fn role(&self) -> &str; 143 144 /// Get the bot's current state 145 fn state(&self) -> String { 146 "running".to_string() 147 } 148 } 149 150 /// A builder for creating bot instances 151 pub struct BotBuilder { 152 bot_id: String, 153 role: String, 154 execution_context: ExecutionContext, 155 } 156 157 impl BotBuilder { 158 pub fn new(bot_id: String, role: String, execution_context: ExecutionContext) -> Self { 159 Self { 160 bot_id, 161 role, 162 execution_context, 163 } 164 } 165 166 pub fn build_context(self, identity: Identity, wallet: Wallet) -> BotContext { 167 BotContext::new(self.execution_context, identity, wallet) 168 } 169 }