use super::{DEFAULT_ENDPOINT, Developer};
use crate::{
commands::StoreFormat,
helpers::args::{parse_private_key, prepare_endpoint},
};
use snarkvm::{
console::network::Network,
ledger::store::helpers::memory::BlockMemory,
prelude::{
Address,
Locator,
VM,
Value,
query::Query,
store::{ConsensusStore, helpers::memory::ConsensusMemory},
},
};
use aleo_std::StorageMode;
use anyhow::Result;
use clap::{Parser, builder::NonEmptyStringValueParser};
use std::str::FromStr;
use ureq::http::Uri;
use zeroize::Zeroize;
#[derive(Debug, Parser)]
#[clap(
group(clap::ArgGroup::new("mode").required(true).multiple(false))
)]
pub struct TransferPrivate {
#[clap(long)]
input_record: String,
#[clap(long)]
recipient: String,
#[clap(long)]
amount: u64,
#[clap(short = 'p', long, group = "key", value_parser=NonEmptyStringValueParser::default())]
private_key: Option<String>,
#[clap(long, group = "key", value_parser=NonEmptyStringValueParser::default())]
private_key_file: Option<String>,
#[clap(long, group = "key")]
dev_key: Option<u16>,
#[clap(short, long, default_value=DEFAULT_ENDPOINT)]
endpoint: Uri,
#[clap(long)]
priority_fee: u64,
#[clap(long)]
fee_record: String,
#[clap(short, long, group = "mode")]
broadcast: Option<Option<Uri>>,
#[clap(short, long, group = "mode")]
dry_run: bool,
#[clap(long, group = "mode")]
store: Option<String>,
#[clap(long, value_enum, default_value_t = StoreFormat::Bytes, requires="store")]
store_format: StoreFormat,
#[clap(long, requires = "broadcast")]
wait: bool,
#[clap(long, default_value_t = 60, requires = "wait")]
timeout: u64,
}
impl Drop for TransferPrivate {
fn drop(&mut self) {
self.private_key.zeroize();
}
}
impl TransferPrivate {
pub fn parse<N: Network>(self) -> Result<String> {
let endpoint = prepare_endpoint(self.endpoint.clone())?;
let query = Query::<N, BlockMemory<N>>::from(endpoint.clone());
let recipient = Address::<N>::from_str(&self.recipient)?;
let private_key = parse_private_key(self.private_key.clone(), self.private_key_file.clone(), self.dev_key)?;
println!("📦 Creating private transfer of {} microcredits to {}...\n", self.amount, recipient);
let transaction = {
let rng = &mut rand::thread_rng();
let store = ConsensusStore::<N, ConsensusMemory<N>>::open(StorageMode::Production)?;
let vm = VM::from(store)?;
let fee_record = Developer::parse_record(&private_key, &self.fee_record)?;
let priority_fee = self.priority_fee;
let input_record = Developer::parse_record(&private_key, &self.input_record)?;
let inputs = [
Value::Record(input_record),
Value::from_str(&format!("{recipient}"))?,
Value::from_str(&format!("{}u64", self.amount))?,
];
vm.execute(
&private_key,
("credits.aleo", "transfer_private"),
inputs.iter(),
Some(fee_record),
priority_fee,
Some(&query),
rng,
)?
};
let locator = Locator::<N>::from_str("credits.aleo/transfer_private")?;
println!("✅ Created private transfer of {} microcredits to {}\n", &self.amount, recipient);
Developer::handle_transaction(
&endpoint,
&self.broadcast,
self.dry_run,
&self.store,
self.store_format,
self.wait,
self.timeout,
transaction,
locator.to_string(),
)
}
}