mirror of
https://github.com/jwinterm/grin-wallet.git
synced 2026-10-17 07:11:36 +02:00
add contract outfile
This commit is contained in:
@@ -1694,12 +1694,10 @@ pub struct ContractNewArgs {
|
||||
pub ttl_blocks: Option<u64>,
|
||||
/// Fee rate in nanogrin per unit of transaction weight
|
||||
pub fee_rate: Option<u32>,
|
||||
/// Override the output Slatepack file
|
||||
pub outfile: Option<String>,
|
||||
/// Select and lock outputs early
|
||||
pub add_outputs: bool,
|
||||
|
||||
// Future features
|
||||
/// Save slatepack to a specific filename
|
||||
pub outfile: Option<String>,
|
||||
}
|
||||
|
||||
impl ContractNewArgs {
|
||||
@@ -1799,12 +1797,12 @@ pub struct ContractSetupArgs {
|
||||
pub minimum_confirmations: Option<u64>,
|
||||
/// Fee rate in nanogrin per unit of transaction weight
|
||||
pub fee_rate: Option<u32>,
|
||||
/// Override the output Slatepack file
|
||||
pub outfile: Option<String>,
|
||||
|
||||
// Future features
|
||||
/// Whether we should automatically sign a receive of any value
|
||||
// pub auto_receive: Option<bool>,
|
||||
/// Save slatepack to a specific filename
|
||||
pub outfile: Option<String>,
|
||||
/// Add outputs
|
||||
pub add_outputs: bool, // lock outputs early
|
||||
}
|
||||
@@ -1937,6 +1935,8 @@ where
|
||||
pub struct ContractRevokeArgs {
|
||||
/// Id of a transaction we want to cancel
|
||||
pub tx_id: u32,
|
||||
/// Override the output Slatepack file
|
||||
pub outfile: Option<String>,
|
||||
}
|
||||
|
||||
pub fn contract_revoke<L, C, K>(
|
||||
@@ -1961,7 +1961,7 @@ where
|
||||
)?;
|
||||
if let Some(slate) = slate_opt {
|
||||
// A revoke has no counterparty, so write the replacement as plaintext.
|
||||
let slate_out = prepare_slatepack(api, keychain_mask, &slate, None, None)?;
|
||||
let slate_out = prepare_slatepack(api, keychain_mask, &slate, None, args.outfile)?;
|
||||
println!("{}", slate_out);
|
||||
} else {
|
||||
println!("Contract revoked. No replacement transaction was created.");
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
//! Test contract revoke, including when a different account is active than the
|
||||
//! one that contributed (and locked) the inputs.
|
||||
// #[macro_use]
|
||||
extern crate grin_wallet_api as api;
|
||||
extern crate grin_wallet_controller as wallet;
|
||||
extern crate grin_wallet_impls as impls;
|
||||
extern crate log;
|
||||
@@ -29,7 +30,7 @@ use std::time::Duration;
|
||||
#[macro_use]
|
||||
mod common;
|
||||
use common::{clean_output_dir, create_wallets, setup};
|
||||
use std::path::PathBuf;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// Revoke the transaction in the requested account when two accounts share a transaction id.
|
||||
fn contract_revoke_other_account_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
@@ -202,7 +203,7 @@ fn wallet_contract_revoke_other_account() -> Result<(), libwallet::Error> {
|
||||
/// built yet) must be resumable: a second revoke detects the now-Unspent inputs that are
|
||||
/// still tagged with the cancelled tx and still produces the self-spend, rather than
|
||||
/// silently doing nothing.
|
||||
fn contract_revoke_resume_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
fn contract_revoke_resume_impl(test_dir: &'static str) -> Result<(), wallet::Error> {
|
||||
let (wallets, _chain, stopper, _bh) =
|
||||
create_wallets(vec![vec![("default", 4)]], test_dir).unwrap();
|
||||
let wallet1 = wallets[0].0.clone();
|
||||
@@ -261,25 +262,19 @@ fn contract_revoke_resume_impl(test_dir: &'static str) -> Result<(), libwallet::
|
||||
},
|
||||
)?;
|
||||
|
||||
// Resume: revoke must still produce the self-spend from the now-Unspent input.
|
||||
let mut revoked = None;
|
||||
wallet::controller::owner_single_use(
|
||||
wallet1.clone(),
|
||||
// Resume through the command path and write the self-spend to the requested file.
|
||||
let outfile = format!("{}/revoke.slatepack", test_dir);
|
||||
let mut owner = api::Owner::new(wallet1.clone(), None, PathBuf::from(test_dir));
|
||||
wallet::command::contract_revoke(
|
||||
&mut owner,
|
||||
mask1,
|
||||
PathBuf::from(test_dir),
|
||||
|api, m| {
|
||||
revoked = api.contract_revoke(
|
||||
m,
|
||||
&ContractRevokeArgsAPI {
|
||||
tx_id,
|
||||
src_acct_name: None,
|
||||
},
|
||||
)?;
|
||||
Ok(())
|
||||
wallet::command::ContractRevokeArgs {
|
||||
tx_id,
|
||||
outfile: Some(outfile.clone()),
|
||||
},
|
||||
)?;
|
||||
assert!(
|
||||
revoked.is_some(),
|
||||
Path::new(&outfile).is_file(),
|
||||
"interrupted revoke should resume and produce a self-spend slate"
|
||||
);
|
||||
|
||||
@@ -289,7 +284,7 @@ fn contract_revoke_resume_impl(test_dir: &'static str) -> Result<(), libwallet::
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wallet_contract_revoke_resume() -> Result<(), libwallet::Error> {
|
||||
fn wallet_contract_revoke_resume() -> Result<(), wallet::Error> {
|
||||
let test_dir = "test_output/contract_revoke_resume";
|
||||
setup(test_dir);
|
||||
contract_revoke_resume_impl(test_dir)?;
|
||||
|
||||
+2
-1
@@ -13,7 +13,8 @@ API does not require manual confirmation, so a wallet using it still needs to sh
|
||||
transaction and ask the user before signing.
|
||||
|
||||
The CLI exchanges Slatepacks. The last `sign` broadcasts the transaction unless
|
||||
`--no-broadcast` is used.
|
||||
`--no-broadcast` is used. `--outfile` overrides the output Slatepack file for `new`, `sign`
|
||||
and `revoke`.
|
||||
|
||||
## Amounts and fees
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@ Separating side effects until the 'save_step' part would make these functions mu
|
||||
clearer to callers.
|
||||
- For a payjoin, `--use-inputs any` picks an input for us; naming the commitment would be
|
||||
clearer, for the API as much as the CLI.
|
||||
- Support `--outfile` for contract slatepacks.
|
||||
- Raise the replacement fee when `revoke` races a transaction already in the mempool.
|
||||
- Merge invoice-proof retrieval with the existing payment-proof API.
|
||||
- Add a Grin node API for kernel lookup by MMR index, then use the witness index instead
|
||||
|
||||
@@ -512,6 +512,11 @@ subcommands:
|
||||
short: b
|
||||
long: ttl_blocks
|
||||
takes_value: true
|
||||
- outfile:
|
||||
help: If present, overrides the filename and location of the output Slatepack file.
|
||||
short: u
|
||||
long: outfile
|
||||
takes_value: true
|
||||
- sign:
|
||||
about: Sign a contract
|
||||
args:
|
||||
@@ -559,6 +564,11 @@ subcommands:
|
||||
help: Fee rate to use when first joining, in nanogrin per unit of transaction weight (defaults to accept_fee_base)
|
||||
long: fee_rate
|
||||
takes_value: true
|
||||
- outfile:
|
||||
help: If present, overrides the filename and location of the output Slatepack file.
|
||||
short: u
|
||||
long: outfile
|
||||
takes_value: true
|
||||
- no-broadcast:
|
||||
help: Don't broadcast the transaction if it was finalized
|
||||
long: no-broadcast
|
||||
@@ -579,3 +589,8 @@ subcommands:
|
||||
short: i
|
||||
long: tx-id
|
||||
takes_value: true
|
||||
- outfile:
|
||||
help: If present, overrides the filename and location of the output Slatepack file.
|
||||
short: u
|
||||
long: outfile
|
||||
takes_value: true
|
||||
|
||||
@@ -1048,6 +1048,7 @@ pub fn parse_contract_new_args(
|
||||
"minimum_confirmations",
|
||||
)?;
|
||||
let fee_rate = parse_contract_fee_rate(args)?;
|
||||
let outfile = parse_optional(args, "outfile")?;
|
||||
let ttl_blocks = match args.value_of("ttl_blocks") {
|
||||
Some(value) => {
|
||||
let blocks = parse_u64(value, "ttl_blocks")?;
|
||||
@@ -1117,8 +1118,7 @@ pub fn parse_contract_new_args(
|
||||
minimum_confirmations,
|
||||
fee_rate,
|
||||
ttl_blocks,
|
||||
// Not yet wired to CLI flags:
|
||||
outfile: None,
|
||||
outfile,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1149,6 +1149,7 @@ pub fn parse_contract_setup_args(
|
||||
None => None,
|
||||
};
|
||||
let fee_rate = parse_contract_fee_rate(args)?;
|
||||
let outfile = parse_optional(args, "outfile")?;
|
||||
let no_payjoin = args.is_present("no-payjoin");
|
||||
let use_inputs = match args.value_of("use-inputs") {
|
||||
Some(v) => {
|
||||
@@ -1192,8 +1193,7 @@ pub fn parse_contract_setup_args(
|
||||
make_outputs: make_outputs,
|
||||
minimum_confirmations,
|
||||
fee_rate,
|
||||
// Not yet wired to CLI flags:
|
||||
outfile: None,
|
||||
outfile,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1233,8 +1233,9 @@ pub fn parse_contract_revoke_args(
|
||||
let tx_id = tx_id_str.parse::<u32>().map_err(|e| {
|
||||
ParseError::ArgumentError(format!("Could not parse tx-id '{}'. e={}", tx_id_str, e))
|
||||
})?;
|
||||
let outfile = parse_optional(args, "outfile")?;
|
||||
|
||||
Ok(command::ContractRevokeArgs { tx_id: tx_id })
|
||||
Ok(command::ContractRevokeArgs { tx_id, outfile })
|
||||
}
|
||||
|
||||
pub fn contract_json_output(args: &ArgMatches<'_>) -> bool {
|
||||
|
||||
@@ -107,6 +107,7 @@ fn contract_command_test_impl(test_dir: &str) -> Result<(), grin_wallet_controll
|
||||
let expected_fee = Transaction::weight_by_iok(1, 1, 0) * fee_rate
|
||||
+ (Transaction::weight_by_iok(0, 0, 1) * fee_rate).div_ceil(2);
|
||||
let fee_rate = fee_rate.to_string();
|
||||
let file_name = format!("{}/wallet1/contract.slatepack", test_dir);
|
||||
|
||||
// Wallet 1 opens a contract sending 1 grin, leaving an unencrypted slatepack because
|
||||
// no --encrypt-for was given
|
||||
@@ -122,11 +123,13 @@ fn contract_command_test_impl(test_dir: &str) -> Result<(), grin_wallet_controll
|
||||
"1",
|
||||
"--fee_rate",
|
||||
&fee_rate,
|
||||
"--outfile",
|
||||
&file_name,
|
||||
];
|
||||
execute_command(&app, test_dir, "wallet1", &client1, arg_vec)?;
|
||||
assert!(std::path::Path::new(&file_name).is_file());
|
||||
|
||||
// Wallet 2 views the contract before signing it
|
||||
let file_name = only_slatepack(test_dir, "wallet1");
|
||||
grin_wallet_controller::controller::owner_single_use(
|
||||
wallet1.clone(),
|
||||
mask1,
|
||||
@@ -284,6 +287,8 @@ fn parses_contract_options() {
|
||||
"2",
|
||||
"--ttl_blocks",
|
||||
"20",
|
||||
"--outfile",
|
||||
"new.slatepack",
|
||||
])
|
||||
.unwrap();
|
||||
let contract = args.subcommand_matches("contract").unwrap();
|
||||
@@ -293,6 +298,7 @@ fn parses_contract_options() {
|
||||
assert_eq!(parsed.minimum_confirmations, 3);
|
||||
assert_eq!(parsed.fee_rate, Some(2));
|
||||
assert_eq!(parsed.ttl_blocks, Some(20));
|
||||
assert_eq!(parsed.outfile.as_deref(), Some("new.slatepack"));
|
||||
|
||||
let expected = grin_wallet_libwallet::contract::types::DEFAULT_MINIMUM_CONFIRMATIONS;
|
||||
let args = app
|
||||
@@ -363,6 +369,7 @@ fn parses_contract_options() {
|
||||
assert_eq!(parsed.fee_rate, None);
|
||||
|
||||
let args = app
|
||||
.clone()
|
||||
.get_matches_from_safe(vec![
|
||||
"grin-wallet",
|
||||
"contract",
|
||||
@@ -371,6 +378,8 @@ fn parses_contract_options() {
|
||||
"3",
|
||||
"--fee_rate",
|
||||
"2",
|
||||
"--outfile",
|
||||
"sign.slatepack",
|
||||
])
|
||||
.unwrap();
|
||||
let contract = args.subcommand_matches("contract").unwrap();
|
||||
@@ -378,6 +387,23 @@ fn parses_contract_options() {
|
||||
let parsed = grin_wallet::cmd::wallet_args::parse_contract_setup_args(sign_args).unwrap();
|
||||
assert_eq!(parsed.minimum_confirmations, Some(3));
|
||||
assert_eq!(parsed.fee_rate, Some(2));
|
||||
assert_eq!(parsed.outfile.as_deref(), Some("sign.slatepack"));
|
||||
|
||||
let args = app
|
||||
.get_matches_from_safe(vec![
|
||||
"grin-wallet",
|
||||
"contract",
|
||||
"revoke",
|
||||
"--tx-id",
|
||||
"1",
|
||||
"--outfile",
|
||||
"revoke.slatepack",
|
||||
])
|
||||
.unwrap();
|
||||
let contract = args.subcommand_matches("contract").unwrap();
|
||||
let revoke_args = contract.subcommand_matches("revoke").unwrap();
|
||||
let parsed = grin_wallet::cmd::wallet_args::parse_contract_revoke_args(revoke_args).unwrap();
|
||||
assert_eq!(parsed.outfile.as_deref(), Some("revoke.slatepack"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user