cargo_tangle/command/deploy/
mbsm.rs

1use alloy_signer_local::PrivateKeySigner;
2use blueprint_chain_setup::tangle::transactions;
3use blueprint_clients::tangle::client::{TangleClient, TangleConfig};
4use blueprint_contexts::tangle::TangleClientContext;
5use blueprint_crypto::sp_core::{SpEcdsa, SpSr25519};
6use blueprint_crypto::tangle_pair_signer::TanglePairSigner;
7use blueprint_keystore::backends::Backend;
8use blueprint_testing_utils::tangle::harness::{ENDOWED_TEST_NAMES, generate_env_from_node_id};
9use dialoguer::console::style;
10use tangle_subxt::subxt::tx::Signer;
11use tempfile::TempDir;
12use url::Url;
13
14/// Deploy the MBSM contract to the chain
15///
16/// # Arguments
17/// * `http_rpc_url` - The URL of the HTTP RPC server
18/// * `force` - Whether to force the deployment
19///
20/// # Errors
21///
22/// Returns an error if the deployment fails
23pub async fn deploy_mbsm(http_rpc_url: Url, force: bool) -> color_eyre::Result<()> {
24    let temp_dir = TempDir::new()?;
25    let mut ws_endpoint = http_rpc_url.clone();
26    ws_endpoint.set_scheme("ws").map_err(|()| {
27        color_eyre::Report::msg(format!(
28            "Failed to set the scheme of the URL to 'ws': {}",
29            ws_endpoint
30        ))
31    })?;
32
33    let temp_path = temp_dir.path().to_path_buf();
34    println!(
35        "{}",
36        style("Checking if the deployment can proceed...")
37            .cyan()
38            .bold()
39    );
40
41    // Set up Alice's environment for MBSM deployment
42    let alice_env = generate_env_from_node_id(
43        ENDOWED_TEST_NAMES[0],
44        http_rpc_url.clone(),
45        ws_endpoint.clone(),
46        temp_path.as_path(),
47    )
48    .await?;
49
50    let alice_keystore = alice_env.keystore();
51    let alice_client = alice_env.tangle_client().await?;
52
53    let alice_sr25519_public = alice_keystore.first_local::<SpSr25519>()?;
54    let alice_sr25519_pair = alice_keystore.get_secret::<SpSr25519>(&alice_sr25519_public)?;
55    let alice_sr25519_signer = TanglePairSigner::new(alice_sr25519_pair.0);
56
57    let alice_ecdsa_public = alice_keystore.first_local::<SpEcdsa>()?;
58    let alice_ecdsa_pair = alice_keystore.get_secret::<SpEcdsa>(&alice_ecdsa_public)?;
59    let alice_ecdsa_signer = TanglePairSigner::new(alice_ecdsa_pair.0);
60    let alice_alloy_key = alice_ecdsa_signer
61        .alloy_key()
62        .map_err(|e| color_eyre::Report::msg(format!("Failed to get Alice's Alloy key: {}", e)))?;
63
64    // Check if MBSM is already deployed
65    let latest_revision = transactions::get_latest_mbsm_revision(&alice_client)
66        .await
67        .map_err(|e| {
68            color_eyre::Report::msg(format!("Failed to get latest MBSM revision: {}", e))
69        })?;
70
71    match latest_revision {
72        Some((rev, addr)) if !force => {
73            println!(
74                "{}",
75                style(format!(
76                    "MBSM is already deployed at revision #{} at address {}",
77                    rev, addr
78                ))
79                .green()
80            );
81            return Ok(());
82        }
83        Some((rev, addr)) => {
84            println!(
85                "{}",
86                style(format!(
87                    "MBSM is already deployed at revision #{} at address {}",
88                    rev, addr
89                ))
90                .yellow()
91            );
92        }
93        None => {
94            println!("{}", style("MBSM is not deployed").yellow());
95        }
96    }
97
98    println!(
99        "{}",
100        style("MBSM is not deployed, deploying now with Alice's account...").cyan()
101    );
102
103    let bytecode = tnt_core_bytecode::bytecode::MASTER_BLUEPRINT_SERVICE_MANAGER;
104    transactions::deploy_new_mbsm_revision(
105        ws_endpoint.as_str(),
106        &alice_client,
107        &alice_sr25519_signer,
108        alice_alloy_key.clone(),
109        bytecode,
110        alloy_primitives::address!("0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
111    )
112    .await
113    .map_err(|e| color_eyre::Report::msg(format!("Failed to deploy MBSM: {}", e)))?;
114
115    println!("{}", style("MBSM deployed successfully").green());
116    Ok(())
117}
118
119/// Check if the MBSM is deployed, and if not, deploy it
120///
121/// # Errors
122///
123/// * Unable to check for existing MBSM revision
124/// * Unable to deploy new MBSM revision
125pub async fn deploy_mbsm_if_needed<T: Signer<TangleConfig>>(
126    ws_endpoint: Url,
127    client: &TangleClient,
128    account: &T,
129    evm_signer: PrivateKeySigner,
130) -> color_eyre::Result<()> {
131    // Check if MBSM is already deployed
132    let latest_revision = transactions::get_latest_mbsm_revision(client)
133        .await
134        .map_err(|e| {
135            color_eyre::Report::msg(format!("Failed to get latest MBSM revision: {}", e))
136        })?;
137
138    if let Some((rev, addr)) = latest_revision {
139        println!(
140            "{}",
141            style(format!(
142                "MBSM is already deployed at revision #{} at address {}",
143                rev, addr
144            ))
145            .green()
146        );
147
148        return Ok(());
149    }
150
151    println!(
152        "{}",
153        style("MBSM is not deployed, deploying now with Alice's account...").cyan()
154    );
155
156    let bytecode = tnt_core_bytecode::bytecode::MASTER_BLUEPRINT_SERVICE_MANAGER;
157    transactions::deploy_new_mbsm_revision(
158        ws_endpoint.as_str(),
159        client,
160        account,
161        evm_signer,
162        bytecode,
163        alloy_primitives::address!("0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
164    )
165    .await
166    .map_err(|e| color_eyre::Report::msg(format!("Failed to deploy MBSM: {}", e)))?;
167
168    println!("{}", style("MBSM deployed successfully").green());
169
170    Ok(())
171}