snarkos_cli/commands/developer/
transfer_private.rs1use super::{DEFAULT_ENDPOINT, Developer};
17use crate::{
18 commands::StoreFormat,
19 helpers::args::{parse_private_key, prepare_endpoint},
20};
21use snarkvm::{
22 console::network::Network,
23 ledger::store::helpers::memory::BlockMemory,
24 prelude::{
25 Address,
26 Locator,
27 VM,
28 Value,
29 query::Query,
30 store::{ConsensusStore, helpers::memory::ConsensusMemory},
31 },
32};
33
34use aleo_std::StorageMode;
35use anyhow::Result;
36use clap::{Parser, builder::NonEmptyStringValueParser};
37use std::{path::PathBuf, str::FromStr};
38use ureq::http::Uri;
39use zeroize::Zeroize;
40
41#[derive(Debug, Parser)]
43#[clap(
44 group(clap::ArgGroup::new("mode").required(true).multiple(false))
45)]
46pub struct TransferPrivate {
47 #[clap(long)]
49 input_record: String,
50 #[clap(long)]
52 recipient: String,
53 #[clap(long)]
55 amount: u64,
56 #[clap(short = 'p', long, group = "key", value_parser=NonEmptyStringValueParser::default())]
58 private_key: Option<String>,
59 #[clap(long, group = "key", value_parser=NonEmptyStringValueParser::default())]
61 private_key_file: Option<String>,
62 #[clap(long, group = "key")]
64 dev_key: Option<u16>,
65 #[clap(short, long, default_value=DEFAULT_ENDPOINT)]
67 endpoint: Uri,
68 #[clap(long)]
70 priority_fee: u64,
71 #[clap(long)]
73 fee_record: String,
74 #[clap(short, long, group = "mode")]
76 broadcast: Option<Option<Uri>>,
77 #[clap(short, long, group = "mode")]
79 dry_run: bool,
80 #[clap(long, group = "mode")]
82 store: Option<String>,
83 #[clap(long, value_enum, default_value_t = StoreFormat::Bytes, requires="store")]
86 store_format: StoreFormat,
87 #[clap(long, requires = "broadcast")]
89 wait: bool,
90 #[clap(long, default_value_t = 60, requires = "wait")]
92 timeout: u64,
93 #[clap(long = "storage_path")]
95 storage_path: Option<PathBuf>,
96}
97
98impl Drop for TransferPrivate {
99 fn drop(&mut self) {
101 self.private_key.zeroize();
102 }
103}
104
105impl TransferPrivate {
106 pub fn parse<N: Network>(self) -> Result<String> {
108 let endpoint = prepare_endpoint(self.endpoint.clone())?;
109
110 let query = Query::<N, BlockMemory<N>>::from(endpoint.clone());
112
113 let recipient = Address::<N>::from_str(&self.recipient)?;
115
116 let private_key = parse_private_key(self.private_key.clone(), self.private_key_file.clone(), self.dev_key)?;
118 println!("📦 Creating private transfer of {} microcredits to {}...\n", self.amount, recipient);
119
120 let transaction = {
122 let rng = &mut rand::thread_rng();
124
125 let storage_mode = match &self.storage_path {
127 Some(path) => StorageMode::Custom(path.clone()),
128 None => StorageMode::Production,
129 };
130 let store = ConsensusStore::<N, ConsensusMemory<N>>::open(storage_mode)?;
131
132 let vm = VM::from(store)?;
134
135 let fee_record = Developer::parse_record(&private_key, &self.fee_record)?;
137 let priority_fee = self.priority_fee;
138
139 let input_record = Developer::parse_record(&private_key, &self.input_record)?;
141 let inputs = [
142 Value::Record(input_record),
143 Value::from_str(&format!("{recipient}"))?,
144 Value::from_str(&format!("{}u64", self.amount))?,
145 ];
146
147 vm.execute(
149 &private_key,
150 ("credits.aleo", "transfer_private"),
151 inputs.iter(),
152 Some(fee_record),
153 priority_fee,
154 Some(&query),
155 rng,
156 )?
157 };
158 let locator = Locator::<N>::from_str("credits.aleo/transfer_private")?;
159 println!("✅ Created private transfer of {} microcredits to {}\n", &self.amount, recipient);
160
161 Developer::handle_transaction(
163 &endpoint,
164 &self.broadcast,
165 self.dry_run,
166 &self.store,
167 self.store_format,
168 self.wait,
169 self.timeout,
170 transaction,
171 locator.to_string(),
172 )
173 }
174}