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