snarkos_cli/commands/developer/
transfer_private.rs1use super::Developer;
17use crate::commands::StoreFormat;
18use snarkvm::{
19 console::network::{CanaryV0, MainnetV0, Network, TestnetV0},
20 ledger::store::helpers::memory::BlockMemory,
21 prelude::{
22 Address,
23 Locator,
24 PrivateKey,
25 VM,
26 Value,
27 query::Query,
28 store::{ConsensusStore, helpers::memory::ConsensusMemory},
29 },
30};
31
32use aleo_std::StorageMode;
33use anyhow::{Result, bail};
34use clap::Parser;
35use std::{path::PathBuf, str::FromStr};
36use zeroize::Zeroize;
37
38#[derive(Debug, Parser)]
40pub struct TransferPrivate {
41 #[clap(default_value = "0", long = "network")]
43 pub network: u16,
44 #[clap(long)]
46 input_record: String,
47 #[clap(long)]
49 recipient: String,
50 #[clap(long)]
52 amount: u64,
53 #[clap(short, long)]
55 private_key: String,
56 #[clap(short, long)]
58 query: String,
59 #[clap(long)]
61 priority_fee: u64,
62 #[clap(long)]
64 fee_record: String,
65 #[clap(short, long, conflicts_with = "dry_run")]
67 broadcast: Option<String>,
68 #[clap(short, long, conflicts_with = "broadcast")]
70 dry_run: bool,
71 #[clap(long)]
73 store: Option<String>,
74 #[clap(long, value_enum, default_value_t = StoreFormat::Bytes)]
77 store_format: StoreFormat,
78 #[clap(long = "storage_path")]
81 pub storage_path: Option<PathBuf>,
82}
83
84impl Drop for TransferPrivate {
85 fn drop(&mut self) {
87 self.private_key.zeroize();
88 }
89}
90
91impl TransferPrivate {
92 #[allow(clippy::format_in_format_args)]
94 pub fn parse(self) -> Result<String> {
95 if !self.dry_run && self.broadcast.is_none() && self.store.is_none() {
97 bail!("❌ Please specify one of the following actions: --broadcast, --dry-run, --store");
98 }
99
100 match self.network {
102 MainnetV0::ID => self.construct_transfer_private::<MainnetV0>(),
103 TestnetV0::ID => self.construct_transfer_private::<TestnetV0>(),
104 CanaryV0::ID => self.construct_transfer_private::<CanaryV0>(),
105 unknown_id => bail!("Unknown network ID ({unknown_id})"),
106 }
107 }
108
109 fn construct_transfer_private<N: Network>(&self) -> Result<String> {
111 let query = Query::<N, BlockMemory<N>>::from(&self.query);
113
114 let recipient = Address::<N>::from_str(&self.recipient)?;
116
117 let private_key = PrivateKey::from_str(&self.private_key)?;
119
120 println!("📦 Creating private transfer of {} microcredits to {}...\n", self.amount, recipient);
121
122 let transaction = {
124 let rng = &mut rand::thread_rng();
126
127 let storage_mode = match &self.storage_path {
129 Some(path) => StorageMode::Custom(path.clone()),
130 None => StorageMode::Production,
131 };
132 let store = ConsensusStore::<N, ConsensusMemory<N>>::open(storage_mode)?;
133
134 let vm = VM::from(store)?;
136
137 let fee_record = Developer::parse_record(&private_key, &self.fee_record)?;
139 let priority_fee = self.priority_fee;
140
141 let input_record = Developer::parse_record(&private_key, &self.input_record)?;
143 let inputs = [
144 Value::Record(input_record),
145 Value::from_str(&format!("{recipient}"))?,
146 Value::from_str(&format!("{}u64", self.amount))?,
147 ];
148
149 vm.execute(
151 &private_key,
152 ("credits.aleo", "transfer_private"),
153 inputs.iter(),
154 Some(fee_record),
155 priority_fee,
156 Some(&query),
157 rng,
158 )?
159 };
160 let locator = Locator::<N>::from_str("credits.aleo/transfer_private")?;
161 println!("✅ Created private transfer of {} microcredits to {}\n", &self.amount, recipient);
162
163 Developer::handle_transaction(
165 &self.broadcast,
166 self.dry_run,
167 &self.store,
168 self.store_format,
169 transaction,
170 locator.to_string(),
171 )
172 }
173}