cargo_tangle/command/service/
request.rs1use color_eyre::Result;
2use dialoguer::console::style;
3use blueprint_clients::tangle::client::OnlineClient;
4use blueprint_crypto::sp_core::SpSr25519;
5use blueprint_crypto::tangle_pair_signer::TanglePairSigner;
6use blueprint_keystore::{Keystore, KeystoreConfig};
7use tangle_subxt::tangle_testnet_runtime::api::runtime_types::sp_arithmetic::per_things::Percent;
8use tangle_subxt::tangle_testnet_runtime::api::runtime_types::tangle_primitives::services::types::{
9 Asset, AssetSecurityRequirement, MembershipModel,
10};
11use crate::wait_for_in_block_success;
12use tangle_subxt::subxt::utils::AccountId32;
13use blueprint_keystore::backends::Backend;
14
15pub async fn request_service(
40 ws_rpc_url: String,
41 blueprint_id: u64,
42 min_exposure_percent: u8,
43 max_exposure_percent: u8,
44 target_operators: Vec<AccountId32>,
45 value: u128,
46 keystore_uri: String,
47 ) -> Result<()> {
49 let client = OnlineClient::from_url(ws_rpc_url.clone()).await?;
50
51 let next_service_id_storage = tangle_subxt::tangle_testnet_runtime::api::storage()
53 .services()
54 .next_instance_id();
55 let next_service_id = client
56 .storage()
57 .at_latest()
58 .await?
59 .fetch_or_default(&next_service_id_storage)
60 .await?;
61
62 let config = KeystoreConfig::new().fs_root(keystore_uri.clone());
63 let keystore = Keystore::new(config).expect("Failed to create keystore");
64 let public = keystore.first_local::<SpSr25519>().unwrap();
65 let pair = keystore.get_secret::<SpSr25519>(&public).unwrap();
66 let signer = TanglePairSigner::new(pair.0);
67
68 let min_operators = u32::try_from(target_operators.len())
69 .map_err(|_| color_eyre::eyre::eyre!("Too many operators"))?;
70 let security_requirements = vec![AssetSecurityRequirement {
71 asset: Asset::Custom(0),
72 min_exposure_percent: Percent(min_exposure_percent),
73 max_exposure_percent: Percent(max_exposure_percent),
74 }];
75
76 println!(
77 "{}",
78 style(format!(
79 "Preparing service request for blueprint ID: {}",
80 blueprint_id
81 ))
82 .cyan()
83 );
84 println!(
85 "{}",
86 style(format!(
87 "Target operators: {} (min: {})",
88 target_operators.len(),
89 min_operators
90 ))
91 .dim()
92 );
93 println!(
94 "{}",
95 style(format!(
96 "Exposure range: {}% - {}%",
97 min_exposure_percent, max_exposure_percent
98 ))
99 .dim()
100 );
101
102 let call = tangle_subxt::tangle_testnet_runtime::api::tx()
103 .services()
104 .request(
105 None,
106 blueprint_id,
107 Vec::new(),
108 target_operators,
109 Vec::default(),
110 security_requirements,
111 1000,
112 Asset::Custom(0),
113 value,
114 MembershipModel::Fixed { min_operators },
115 );
116
117 println!("{}", style("Submitting Service Request...").cyan());
118 let res = client
119 .tx()
120 .sign_and_submit_then_watch_default(&call, &signer)
121 .await?;
122 wait_for_in_block_success(res).await;
123
124 println!(
125 "{}",
126 style("Service Request submitted successfully").green()
127 );
128
129 println!(
130 "{}",
131 style(format!("Service ID: {}", next_service_id))
132 .green()
133 .bold()
134 );
135
136 Ok(())
137}