snarkos_cli/commands/developer/
transfer_private.rs1use super::Developer;
17use snarkvm::{
18 console::network::{CanaryV0, MainnetV0, Network, TestnetV0},
19 ledger::store::helpers::memory::BlockMemory,
20 prelude::{
21 Address,
22 Locator,
23 PrivateKey,
24 VM,
25 Value,
26 query::Query,
27 store::{ConsensusStore, helpers::memory::ConsensusMemory},
28 },
29};
30
31use aleo_std::StorageMode;
32use anyhow::{Result, bail};
33use clap::Parser;
34use std::{path::PathBuf, str::FromStr};
35use zeroize::Zeroize;
36
37#[derive(Debug, Parser)]
39pub struct TransferPrivate {
40 #[clap(default_value = "0", long = "network")]
42 pub network: u16,
43 #[clap(long)]
45 input_record: String,
46 #[clap(long)]
48 recipient: String,
49 #[clap(long)]
51 amount: u64,
52 #[clap(short, long)]
54 private_key: String,
55 #[clap(short, long)]
57 query: String,
58 #[clap(long)]
60 priority_fee: u64,
61 #[clap(long)]
63 fee_record: String,
64 #[clap(short, long, conflicts_with = "dry_run")]
66 broadcast: Option<String>,
67 #[clap(short, long, conflicts_with = "broadcast")]
69 dry_run: bool,
70 #[clap(long)]
72 store: Option<String>,
73 #[clap(long = "storage_path")]
76 pub storage_path: Option<PathBuf>,
77}
78
79impl Drop for TransferPrivate {
80 fn drop(&mut self) {
82 self.private_key.zeroize();
83 }
84}
85
86impl TransferPrivate {
87 #[allow(clippy::format_in_format_args)]
89 pub fn parse(self) -> Result<String> {
90 if !self.dry_run && self.broadcast.is_none() && self.store.is_none() {
92 bail!("❌ Please specify one of the following actions: --broadcast, --dry-run, --store");
93 }
94
95 match self.network {
97 MainnetV0::ID => self.construct_transfer_private::<MainnetV0>(),
98 TestnetV0::ID => self.construct_transfer_private::<TestnetV0>(),
99 CanaryV0::ID => self.construct_transfer_private::<CanaryV0>(),
100 unknown_id => bail!("Unknown network ID ({unknown_id})"),
101 }
102 }
103
104 fn construct_transfer_private<N: Network>(&self) -> Result<String> {
106 let query = Query::<N, BlockMemory<N>>::from(&self.query);
108
109 let recipient = Address::<N>::from_str(&self.recipient)?;
111
112 let private_key = PrivateKey::from_str(&self.private_key)?;
114
115 println!("📦 Creating private transfer of {} microcredits to {}...\n", self.amount, recipient);
116
117 let transaction = {
119 let rng = &mut rand::thread_rng();
121
122 let storage_mode = match &self.storage_path {
124 Some(path) => StorageMode::Custom(path.clone()),
125 None => StorageMode::Production,
126 };
127 let store = ConsensusStore::<N, ConsensusMemory<N>>::open(storage_mode)?;
128
129 let vm = VM::from(store)?;
131
132 let fee_record = Developer::parse_record(&private_key, &self.fee_record)?;
134 let priority_fee = self.priority_fee;
135
136 let input_record = Developer::parse_record(&private_key, &self.input_record)?;
138 let inputs = [
139 Value::Record(input_record),
140 Value::from_str(&format!("{}", recipient))?,
141 Value::from_str(&format!("{}u64", self.amount))?,
142 ];
143
144 vm.execute(
146 &private_key,
147 ("credits.aleo", "transfer_private"),
148 inputs.iter(),
149 Some(fee_record),
150 priority_fee,
151 Some(&query),
152 rng,
153 )?
154 };
155 let locator = Locator::<N>::from_str("credits.aleo/transfer_private")?;
156 println!("✅ Created private transfer of {} microcredits to {}\n", &self.amount, recipient);
157
158 Developer::handle_transaction(&self.broadcast, self.dry_run, &self.store, transaction, locator.to_string())
160 }
161}