mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-06 21:34:00 -05:00
drk/interactive: added missing tx-from-calls subcommand
This commit is contained in:
@@ -55,22 +55,6 @@ pub async fn parse_tx_from_stdin() -> Result<Transaction> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Auxiliary function to parse base64-encoded contract calls from stdin.
|
||||
pub async fn parse_calls_from_stdin() -> Result<Vec<ContractCallImport>> {
|
||||
let lines = stdin().lines();
|
||||
|
||||
let mut calls = vec![];
|
||||
|
||||
for line in lines {
|
||||
let Some(line) = base64::decode(&line?) else {
|
||||
return Err(Error::ParseFailed("Failed to decode base64"))
|
||||
};
|
||||
calls.push(deserialize_async(&line).await?);
|
||||
}
|
||||
|
||||
Ok(calls)
|
||||
}
|
||||
|
||||
/// Auxiliary function to parse a base64 encoded transaction from
|
||||
/// provided input or fallback to stdin if its empty.
|
||||
pub async fn parse_tx_from_input(input: &[String]) -> Result<Transaction> {
|
||||
@@ -84,6 +68,36 @@ pub async fn parse_tx_from_input(input: &[String]) -> Result<Transaction> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Auxiliary function to parse base64 encoded contract calls from stdin.
|
||||
pub async fn parse_calls_from_stdin() -> Result<Vec<ContractCallImport>> {
|
||||
let lines = stdin().lines();
|
||||
let mut calls = vec![];
|
||||
for line in lines {
|
||||
let Some(line) = base64::decode(&line?) else {
|
||||
return Err(Error::ParseFailed("Failed to decode base64"))
|
||||
};
|
||||
calls.push(deserialize_async(&line).await?);
|
||||
}
|
||||
Ok(calls)
|
||||
}
|
||||
|
||||
/// Auxiliary function to parse base64 encoded contract calls from
|
||||
/// provided input or fallback to stdin if its empty.
|
||||
pub async fn parse_calls_from_input(input: &[String]) -> Result<Vec<ContractCallImport>> {
|
||||
if input.is_empty() {
|
||||
return parse_calls_from_stdin().await
|
||||
}
|
||||
|
||||
let mut calls = vec![];
|
||||
for line in input {
|
||||
let Some(line) = base64::decode(line) else {
|
||||
return Err(Error::ParseFailed("Failed to decode base64"))
|
||||
};
|
||||
calls.push(deserialize_async(&line).await?);
|
||||
}
|
||||
Ok(calls)
|
||||
}
|
||||
|
||||
/// Auxiliary function to parse provided string into a values pair.
|
||||
pub fn parse_value_pair(s: &str) -> Result<(u64, u64)> {
|
||||
let v: Vec<&str> = s.split(':').collect();
|
||||
@@ -391,8 +405,12 @@ pub fn generate_completions(shell: &str) -> Result<String> {
|
||||
.about("Attach the fee call to a transaction given from stdin");
|
||||
|
||||
// TxFromCalls
|
||||
let calls_map =
|
||||
Arg::with_name("calls-map").help("Optional parent/children dependency map for the calls");
|
||||
|
||||
let tx_from_calls = SubCommand::with_name("tx-from-calls")
|
||||
.about("Create a transaction from newline-separated calls from stdin");
|
||||
.about("Create a transaction from newline-separated calls from stdin")
|
||||
.args(&[calls_map]);
|
||||
|
||||
// Inspect
|
||||
let inspect = SubCommand::with_name("inspect").about("Inspect a transaction from stdin");
|
||||
|
||||
@@ -60,8 +60,8 @@ use darkfi_serial::{deserialize_async, serialize_async};
|
||||
use crate::{
|
||||
cli_util::{
|
||||
append_or_print, display_mining_config, generate_completions, kaching,
|
||||
parse_mining_config_from_input, parse_token_pair, parse_tx_from_input, parse_value_pair,
|
||||
print_output,
|
||||
parse_calls_from_input, parse_mining_config_from_input, parse_token_pair, parse_tree,
|
||||
parse_tx_from_input, parse_value_pair, print_output, tx_from_calls_mapped,
|
||||
},
|
||||
common::*,
|
||||
dao::{DaoParams, ProposalRecord},
|
||||
@@ -94,6 +94,9 @@ fn help(output: &mut Vec<String>) {
|
||||
output.push(String::from("\tdao: DAO functionalities"));
|
||||
output
|
||||
.push(String::from("\tattach-fee: Attach the fee call to a transaction given from stdin"));
|
||||
output.push(String::from(
|
||||
"\ttx-from-calls: Create a transaction from newline-separated calls from stdin",
|
||||
));
|
||||
output.push(String::from("\tinspect: Inspect a transaction from stdin"));
|
||||
output.push(String::from("\tbroadcast: Read a transaction from stdin and broadcast it"));
|
||||
output.push(String::from(
|
||||
@@ -207,6 +210,11 @@ fn completion(buffer: &str, lc: &mut Vec<String>) {
|
||||
return
|
||||
}
|
||||
|
||||
if last.starts_with("tx") {
|
||||
lc.push(prefix + "tx-from-calls");
|
||||
return
|
||||
}
|
||||
|
||||
if last.starts_with("i") {
|
||||
lc.push(prefix + "inspect");
|
||||
return
|
||||
@@ -378,6 +386,7 @@ fn hints(buffer: &str) -> Option<(String, i32, bool)> {
|
||||
"contract export-data " => Some(("<tx-hash>".to_string(), color, bold)),
|
||||
"contract deploy " => Some(("<deploy-auth> <wasm-path> [deploy-ix]".to_string(), color, bold)),
|
||||
"contract lock " => Some(("<deploy-auth>".to_string(), color, bold)),
|
||||
"tx-from-calls " => Some(("[calls-map]".to_string(), color, bold)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -536,6 +545,7 @@ pub async fn interactive(
|
||||
"otc" => handle_otc(drk, &parts, &input, &mut output).await,
|
||||
"dao" => handle_dao(drk, &parts, &input, &mut output).await,
|
||||
"attach-fee" => handle_attach_fee(drk, &input, &mut output).await,
|
||||
"tx-from-calls" => handle_tx_from_calls(&parts, &input, &mut output).await,
|
||||
"inspect" => handle_inspect(&input, &mut output).await,
|
||||
"broadcast" => handle_broadcast(drk, &input, &mut output).await,
|
||||
"subscribe" => {
|
||||
@@ -2341,6 +2351,79 @@ async fn handle_attach_fee(drk: &DrkPtr, input: &[String], output: &mut Vec<Stri
|
||||
}
|
||||
}
|
||||
|
||||
/// Auxiliary function to define the tx from calls command handling.
|
||||
async fn handle_tx_from_calls(parts: &[&str], input: &[String], output: &mut Vec<String>) {
|
||||
// Check correct subcommand structure
|
||||
if parts.len() != 1 && parts.len() != 2 {
|
||||
output.push(String::from("Malformed `tx-from-calls` subcommand"));
|
||||
output.push(String::from("Usage: tx-from-calls [calls-map]"));
|
||||
return
|
||||
}
|
||||
|
||||
// Parse calls
|
||||
let calls = match parse_calls_from_input(input).await {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
output.push(format!("Error while parsing transaction calls: {e}"));
|
||||
return
|
||||
}
|
||||
};
|
||||
if calls.is_empty() {
|
||||
output.push(String::from("No calls were parsed"));
|
||||
return
|
||||
}
|
||||
|
||||
// If there is a given map, parse it, otherwise construct a
|
||||
// linear map.
|
||||
let calls_map = if parts.len() == 2 {
|
||||
match parse_tree(parts[1]) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
output.push(format!("Failed parsing calls map: {e}"));
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mut calls_map = Vec::with_capacity(calls.len());
|
||||
for (i, _) in calls.iter().enumerate() {
|
||||
calls_map.push((i, vec![]));
|
||||
}
|
||||
calls_map
|
||||
};
|
||||
if calls_map.len() != calls.len() {
|
||||
output.push(String::from("Calls map size not equal to parsed calls"));
|
||||
return
|
||||
}
|
||||
|
||||
// Create a transaction from the mapped calls.
|
||||
let (mut tx_builder, signature_secrets) = match tx_from_calls_mapped(&calls, &calls_map) {
|
||||
Ok(pair) => pair,
|
||||
Err(e) => {
|
||||
output.push(format!("Failed to create a transaction from the mapped calls: {e}"));
|
||||
return
|
||||
}
|
||||
};
|
||||
|
||||
// Now build and sign the tx
|
||||
let mut tx = match tx_builder.build() {
|
||||
Ok(tx) => tx,
|
||||
Err(e) => {
|
||||
output.push(format!("Failed to build the transaction: {e}"));
|
||||
return
|
||||
}
|
||||
};
|
||||
let sigs = match tx.create_sigs(&signature_secrets) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
output.push(format!("Failed to create the transaction signatures: {e}"));
|
||||
return
|
||||
}
|
||||
};
|
||||
tx.signatures.push(sigs);
|
||||
|
||||
output.push(base64::encode(&serialize_async(&tx).await));
|
||||
}
|
||||
|
||||
/// Auxiliary function to define the inspect command handling.
|
||||
async fn handle_inspect(input: &[String], output: &mut Vec<String>) {
|
||||
match parse_tx_from_input(input).await {
|
||||
|
||||
@@ -180,8 +180,7 @@ enum Subcmd {
|
||||
|
||||
/// Create a transaction from newline-separated calls from stdin
|
||||
TxFromCalls {
|
||||
#[structopt(long = "map")]
|
||||
/// The parent/children dependency map for the calls
|
||||
/// Optional parent/children dependency map for the calls
|
||||
calls_map: Option<String>,
|
||||
},
|
||||
|
||||
@@ -2024,8 +2023,12 @@ async fn realmain(args: Args, ex: ExecutorPtr) -> Result<()> {
|
||||
}
|
||||
|
||||
Subcmd::TxFromCalls { calls_map } => {
|
||||
// Parse calls
|
||||
let calls = parse_calls_from_stdin().await?;
|
||||
assert!(!calls.is_empty());
|
||||
if calls.is_empty() {
|
||||
eprintln!("No calls were parsed");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// If there is a given map, parse it, otherwise construct a
|
||||
// linear map.
|
||||
@@ -2033,7 +2036,7 @@ async fn realmain(args: Args, ex: ExecutorPtr) -> Result<()> {
|
||||
Some(cmap) => match parse_tree(&cmap) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
eprintln!("Failed parsing calls map: {}", e);
|
||||
eprintln!("Failed parsing calls map: {e}");
|
||||
exit(1);
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user