cargo_tangle/command/run/
tangle.rs1use alloy_primitives::Address;
2use blueprint_manager::config::{
3 BlueprintManagerConfig, BlueprintManagerContext, Paths, SourceType,
4};
5use blueprint_manager::executor::run_blueprint_manager;
6use blueprint_runner::config::{BlueprintEnvironment, ProtocolSettings};
7use blueprint_runner::tangle::config::TangleProtocolSettings;
8use color_eyre::eyre::Result;
9use dialoguer::console::style;
10use indicatif::{ProgressBar, ProgressStyle};
11use std::path::PathBuf;
12use std::time::Duration;
13use tokio::signal;
14use url::Url;
15
16#[derive(Clone)]
17pub struct RunOpts {
18 pub http_rpc_url: Url,
19 pub ws_rpc_url: Url,
20 pub blueprint_id: u64,
21 pub service_id: Option<u64>,
22 pub tangle_contract: Address,
23 pub staking_contract: Address,
24 pub status_registry_contract: Address,
25 pub keystore_path: String,
26 pub data_dir: Option<PathBuf>,
27 pub allow_unchecked_attestations: bool,
28 pub registration_mode: bool,
29 pub registration_capture_only: bool,
30 pub preferred_source: SourceType,
31 pub use_vm: bool,
32 pub dry_run: bool,
33 pub shutdown_after: Option<Duration>,
34}
35
36pub async fn run_blueprint(opts: RunOpts) -> Result<()> {
37 let mut blueprint_config = BlueprintEnvironment::default();
38 blueprint_config.http_rpc_endpoint = opts.http_rpc_url;
39 blueprint_config.ws_rpc_endpoint = opts.ws_rpc_url;
40 blueprint_config.keystore_uri = opts.keystore_path;
41 blueprint_config.data_dir = opts.data_dir.unwrap_or_else(|| PathBuf::from("./data"));
42 blueprint_config.registration_mode = opts.registration_mode;
43 blueprint_config.registration_capture_only = opts.registration_capture_only;
44 blueprint_config.dry_run = opts.dry_run;
45 blueprint_config.protocol_settings = ProtocolSettings::Tangle(TangleProtocolSettings {
46 blueprint_id: opts.blueprint_id,
47 service_id: opts.service_id,
48 tangle_contract: opts.tangle_contract,
49 staking_contract: opts.staking_contract,
50 status_registry_contract: opts.status_registry_contract,
51 });
52
53 #[allow(unused_mut)]
54 let mut blueprint_manager_config = BlueprintManagerConfig {
55 paths: Paths {
56 keystore_uri: blueprint_config.keystore_uri.clone(),
57 data_dir: blueprint_config.data_dir.clone(),
58 ..Default::default()
59 },
60 verbose: 2,
61 pretty: true,
62 instance_id: Some(format!("Blueprint-{}", opts.blueprint_id)),
63 allow_unchecked_attestations: opts.allow_unchecked_attestations,
64 preferred_source: opts.preferred_source,
65 ..Default::default()
66 };
67
68 #[cfg(feature = "vm-debug")]
69 {
70 blueprint_manager_config.vm_sandbox_options.no_vm = !opts.use_vm;
71 }
72
73 let ctx = BlueprintManagerContext::new(blueprint_manager_config).await?;
74
75 println!(
76 "{}",
77 style(format!(
78 "Starting blueprint manager for blueprint ID: {}",
79 opts.blueprint_id
80 ))
81 .cyan()
82 .bold()
83 );
84
85 let shutdown_after = opts.shutdown_after;
86 let shutdown_signal = async move {
87 if let Some(duration) = shutdown_after {
88 tokio::select! {
89 _ = signal::ctrl_c() => {
90 println!(
91 "{}",
92 style("Received shutdown signal, stopping blueprint manager")
93 .yellow()
94 .bold()
95 );
96 }
97 _ = tokio::time::sleep(duration) => {
98 println!(
99 "{}",
100 style("Auto-shutdown window elapsed, stopping blueprint manager")
101 .yellow()
102 .bold()
103 );
104 }
105 }
106 } else {
107 let _ = signal::ctrl_c().await;
108 println!(
109 "{}",
110 style("Received shutdown signal, stopping blueprint manager")
111 .yellow()
112 .bold()
113 );
114 }
115 };
116
117 println!(
118 "{}",
119 style("Preparing Blueprint to run, this may take a few minutes...").cyan()
120 );
121
122 let pb = ProgressBar::new_spinner();
123 pb.set_style(
124 ProgressStyle::default_spinner()
125 .tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈ ")
126 .template("{spinner:.blue} {msg}")
127 .unwrap(),
128 );
129 pb.set_message("Initializing Blueprint");
130 pb.enable_steady_tick(Duration::from_millis(100));
131
132 let mut handle = run_blueprint_manager(ctx, blueprint_config, shutdown_signal).await?;
133
134 pb.finish_with_message("Blueprint initialized successfully!");
135
136 println!(
137 "{}",
138 style("Starting blueprint execution...").green().bold()
139 );
140 handle.start()?;
141
142 println!(
143 "{}",
144 style("Blueprint is running. Press Ctrl+C to stop.").cyan()
145 );
146 handle.await?;
147
148 println!("{}", style("Blueprint manager has stopped").green());
149 Ok(())
150}