1use blake3::Hash;
2use chrono::{DateTime, Local};
3use crossbeam_channel::{Receiver, Sender};
4use solana_clock::Clock;
6use solana_epoch_info::EpochInfo;
7use solana_message::inner_instruction::InnerInstructionsList;
8use solana_pubkey::Pubkey;
9use solana_signature::Signature;
10use solana_transaction::versioned::VersionedTransaction;
11use solana_transaction_context::TransactionReturnData;
12use solana_transaction_error::TransactionError;
13use txtx_addon_network_svm_types::subgraph::SubgraphRequest;
14
15use std::{collections::HashMap, path::PathBuf};
16use txtx_addon_kit::types::types::Value;
17use uuid::Uuid;
18
19pub const DEFAULT_RPC_URL: &str = "https://api.mainnet-beta.solana.com";
20
21#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
22pub struct TransactionMetadata {
23 pub signature: Signature,
24 pub logs: Vec<String>,
25 pub inner_instructions: InnerInstructionsList,
26 pub compute_units_consumed: u64,
27 pub return_data: TransactionReturnData,
28}
29
30#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
31#[serde(rename_all = "camelCase")]
32pub enum TransactionConfirmationStatus {
33 Processed,
34 Confirmed,
35 Finalized,
36}
37
38#[derive(Clone, Debug, PartialEq, Eq, Default, Serialize, Deserialize)]
39pub enum BlockProductionMode {
40 #[default]
41 Clock,
42 Transaction,
43 Manual,
44}
45
46#[derive(Debug, Clone)]
47pub struct Collection {
48 pub uuid: Uuid,
49 pub name: String,
50 pub entries: Vec<SubgraphDataEntry>,
51}
52
53#[derive(Debug, Clone)]
54pub struct SubgraphDataEntry {
55 pub uuid: Uuid,
57 pub values: HashMap<String, Value>,
59 pub block_height: u64,
61 pub transaction_hash: Hash,
63}
64
65impl SubgraphDataEntry {
66 pub fn new(values: HashMap<String, Value>, block_height: u64, tx_hash: [u8; 32]) -> Self {
67 Self {
68 uuid: Uuid::new_v4(),
69 values,
70 block_height,
71 transaction_hash: Hash::from_bytes(tx_hash),
72 }
73 }
74}
75
76#[derive(Debug)]
77pub enum SubgraphEvent {
78 EndpointReady,
79 InfoLog(DateTime<Local>, String),
80 ErrorLog(DateTime<Local>, String),
81 WarnLog(DateTime<Local>, String),
82 DebugLog(DateTime<Local>, String),
83 Shutdown,
84}
85
86impl SubgraphEvent {
87 pub fn info<S>(msg: S) -> Self
88 where
89 S: Into<String>,
90 {
91 Self::InfoLog(Local::now(), msg.into())
92 }
93
94 pub fn warn<S>(msg: S) -> Self
95 where
96 S: Into<String>,
97 {
98 Self::WarnLog(Local::now(), msg.into())
99 }
100
101 pub fn error<S>(msg: S) -> Self
102 where
103 S: Into<String>,
104 {
105 Self::ErrorLog(Local::now(), msg.into())
106 }
107
108 pub fn debug<S>(msg: S) -> Self
109 where
110 S: Into<String>,
111 {
112 Self::DebugLog(Local::now(), msg.into())
113 }
114}
115
116#[derive(Debug, Clone, Deserialize, Serialize)]
117pub enum SchemaDataSourcingEvent {
118 Rountrip(Uuid),
119 ApplyEntry(Uuid, Vec<u8>, u64, [u8; 32]),
120}
121
122#[derive(Debug, Clone)]
123pub enum SubgraphCommand {
124 CreateSubgraph(Uuid, SubgraphRequest, Sender<String>),
125 ObserveSubgraph(Receiver<SchemaDataSourcingEvent>),
126 Shutdown,
127}
128
129#[derive(Debug)]
130pub enum SimnetEvent {
131 Ready,
132 Connected(String),
133 Aborted(String),
134 Shutdown,
135 ClockUpdate(Clock),
136 EpochInfoUpdate(EpochInfo),
137 BlockHashExpired,
138 InfoLog(DateTime<Local>, String),
139 ErrorLog(DateTime<Local>, String),
140 WarnLog(DateTime<Local>, String),
141 DebugLog(DateTime<Local>, String),
142 PluginLoaded(String),
143 TransactionReceived(DateTime<Local>, VersionedTransaction),
144 TransactionProcessed(
145 DateTime<Local>,
146 TransactionMetadata,
147 Option<TransactionError>,
148 ),
149 AccountUpdate(DateTime<Local>, Pubkey),
150}
151
152impl SimnetEvent {
153 pub fn info<S>(msg: S) -> Self
154 where
155 S: Into<String>,
156 {
157 Self::InfoLog(Local::now(), msg.into())
158 }
159
160 pub fn warn<S>(msg: S) -> Self
161 where
162 S: Into<String>,
163 {
164 Self::WarnLog(Local::now(), msg.into())
165 }
166
167 pub fn error<S>(msg: S) -> Self
168 where
169 S: Into<String>,
170 {
171 Self::ErrorLog(Local::now(), msg.into())
172 }
173
174 pub fn debug<S>(msg: S) -> Self
175 where
176 S: Into<String>,
177 {
178 Self::DebugLog(Local::now(), msg.into())
179 }
180
181 pub fn transaction_processed(meta: TransactionMetadata, err: Option<TransactionError>) -> Self {
182 Self::TransactionProcessed(Local::now(), meta, err)
183 }
184
185 pub fn transaction_received(tx: VersionedTransaction) -> Self {
186 Self::TransactionReceived(Local::now(), tx)
187 }
188
189 pub fn account_update(pubkey: Pubkey) -> Self {
190 Self::AccountUpdate(Local::now(), pubkey)
191 }
192}
193
194#[derive(Debug)]
195pub enum TransactionStatusEvent {
196 Success(TransactionConfirmationStatus),
197 SimulationFailure((TransactionError, TransactionMetadata)),
198 ExecutionFailure((TransactionError, TransactionMetadata)),
199}
200
201#[derive(Debug)]
202pub enum SimnetCommand {
203 SlotForward(Option<Hash>),
204 SlotBackward(Option<Hash>),
205 UpdateClock(ClockCommand),
206 UpdateBlockProductionMode(BlockProductionMode),
207 TransactionReceived(
208 Option<Hash>,
209 VersionedTransaction,
210 Sender<TransactionStatusEvent>,
211 bool,
212 ),
213 Terminate(Option<Hash>),
214}
215
216#[derive(Debug)]
217pub enum ClockCommand {
218 Pause,
219 Resume,
220 Toggle,
221 UpdateSlotInterval(u64),
222}
223
224pub enum ClockEvent {
225 Tick,
226 ExpireBlockHash,
227}
228
229#[derive(Clone, Debug, Default)]
230pub struct SurfpoolConfig {
231 pub simnets: Vec<SimnetConfig>,
232 pub rpc: RpcConfig,
233 pub subgraph: SubgraphConfig,
234 pub plugin_config_path: Vec<PathBuf>,
235}
236
237#[derive(Clone, Debug)]
238pub struct SimnetConfig {
239 pub remote_rpc_url: String,
240 pub slot_time: u64,
241 pub block_production_mode: BlockProductionMode,
242 pub airdrop_addresses: Vec<Pubkey>,
243 pub airdrop_token_amount: u64,
244}
245
246impl Default for SimnetConfig {
247 fn default() -> Self {
248 Self {
249 remote_rpc_url: DEFAULT_RPC_URL.to_string(),
250 slot_time: 0,
251 block_production_mode: BlockProductionMode::Clock,
252 airdrop_addresses: vec![],
253 airdrop_token_amount: 0,
254 }
255 }
256}
257
258#[derive(Clone, Debug, Default)]
259pub struct SubgraphConfig {}
260
261#[derive(Clone, Debug)]
262pub struct RpcConfig {
263 pub bind_host: String,
264 pub bind_port: u16,
265}
266
267impl RpcConfig {
268 pub fn get_socket_address(&self) -> String {
269 format!("{}:{}", self.bind_host, self.bind_port)
270 }
271}
272
273#[derive(Debug, Clone, Deserialize, Serialize)]
274pub struct SubgraphPluginConfig {
275 pub uuid: Uuid,
276 pub ipc_token: String,
277 pub subgraph_request: SubgraphRequest,
278}
279
280impl Default for RpcConfig {
281 fn default() -> Self {
282 Self {
283 bind_host: "127.0.0.1".to_string(),
284 bind_port: 8899,
285 }
286 }
287}
288
289#[derive(Serialize, Deserialize, Clone, Debug)]
290pub struct SvmSimnetInitializationRequest {
291 pub domain: String,
292 pub block_production_mode: BlockProductionMode,
293 pub datasource_rpc_url: String,
294}
295
296#[derive(Serialize, Deserialize, Clone, Debug)]
297pub enum SvmSimnetCommand {
298 Init(SvmSimnetInitializationRequest),
299}
300
301#[derive(Serialize, Deserialize)]
302pub struct CreateNetworkRequest {
303 pub workspace_id: Uuid,
304 pub name: String,
305 pub description: Option<String>,
306 pub datasource_rpc_url: String,
307 pub block_production_mode: BlockProductionMode,
308}
309
310impl CreateNetworkRequest {
311 pub fn new(
312 workspace_id: Uuid,
313 name: String,
314 description: Option<String>,
315 datasource_rpc_url: String,
316 block_production_mode: BlockProductionMode,
317 ) -> Self {
318 Self {
319 workspace_id,
320 name,
321 description,
322 datasource_rpc_url,
323 block_production_mode: block_production_mode,
324 }
325 }
326}
327
328#[derive(Serialize, Deserialize)]
329pub struct CreateNetworkResponse {
330 pub rpc_url: String,
331}