mirror of
https://github.com/mimblewimble/grin-wallet.git
synced 2025-01-20 19:11:09 +03:00
Final Owner API Changes (#32)
* node height return value and documentation * rustfmt * add parameter struct for initiate tx functions * rustfmt * change tx estimate to use InitTxArgs * rustfmt * transaction estimate * rustfmt * initiate tx args fixed * add send args to init * rustfmt * last owner api documentation
This commit is contained in:
parent
7b8fe92f53
commit
427f42c552
16 changed files with 698 additions and 632 deletions
|
@ -16,7 +16,7 @@
|
|||
|
||||
use crate::keychain::Keychain;
|
||||
use crate::libwallet::slate::Slate;
|
||||
use crate::libwallet::types::{BlockFees, CbData, NodeClient, WalletBackend};
|
||||
use crate::libwallet::types::{BlockFees, CbData, InitTxArgs, NodeClient, WalletBackend};
|
||||
use crate::libwallet::ErrorKind;
|
||||
use crate::Foreign;
|
||||
use easy_jsonrpc;
|
||||
|
@ -416,16 +416,16 @@ pub fn run_doctest_foreign(
|
|||
let amount = 60_000_000_000;
|
||||
let mut w = wallet1.lock();
|
||||
w.open_with_credentials().unwrap();
|
||||
let slate = api_impl::owner::initiate_tx(
|
||||
&mut *w, None, // account
|
||||
amount, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None, None, true,
|
||||
)
|
||||
.unwrap();
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate = api_impl::owner::initiate_tx(&mut *w, args, true).unwrap();
|
||||
println!("INIT SLATE");
|
||||
// Spit out slate for input to finalize_tx
|
||||
println!("{}", serde_json::to_string_pretty(&slate).unwrap());
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
use grin_wallet_util::grin_core as core;
|
||||
use grin_wallet_util::grin_keychain as keychain;
|
||||
use grin_wallet_util::grin_util as util;
|
||||
extern crate grin_wallet_impls as impls;
|
||||
extern crate grin_wallet_libwallet as libwallet;
|
||||
|
||||
extern crate failure_derive;
|
||||
|
|
444
api/src/owner.rs
444
api/src/owner.rs
|
@ -21,14 +21,15 @@ use std::sync::Arc;
|
|||
use uuid::Uuid;
|
||||
|
||||
use crate::core::core::Transaction;
|
||||
use crate::impls::{HTTPWalletCommAdapter, KeybaseWalletCommAdapter};
|
||||
use crate::keychain::{Identifier, Keychain};
|
||||
use crate::libwallet::api_impl::owner;
|
||||
use crate::libwallet::slate::Slate;
|
||||
use crate::libwallet::types::{
|
||||
AcctPathMapping, NodeClient, OutputCommitMapping, TxEstimation, TxLogEntry, WalletBackend,
|
||||
WalletInfo,
|
||||
AcctPathMapping, InitTxArgs, NodeClient, NodeHeightResult, OutputCommitMapping, TxLogEntry,
|
||||
WalletBackend, WalletInfo,
|
||||
};
|
||||
use crate::libwallet::Error;
|
||||
use crate::libwallet::{Error, ErrorKind};
|
||||
|
||||
/// Main interface into all wallet API functions.
|
||||
/// Wallet APIs are split into two seperate blocks of functionality
|
||||
|
@ -431,37 +432,15 @@ where
|
|||
/// as via file transfer,) the lock call should happen immediately (before the file is sent
|
||||
/// to the recipient).
|
||||
///
|
||||
/// If the `send_args` [`InitTxSendArgs`](../grin_wallet_libwallet/types/struct.InitTxSendArgs.html),
|
||||
/// of the [`args`](../grin_wallet_libwallet/types/struct.InitTxArgs.html), field is Some, this
|
||||
/// function will attempt to perform a synchronous send to the recipient specified in the `dest`
|
||||
/// field according to the `method` field, and will also finalize and post the transaction if
|
||||
/// the `finalize` field is set.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `src_acct_name` - The human readable account name from which to draw outputs
|
||||
/// for the transaction, overriding whatever the active account is as set via the
|
||||
/// [`set_active_account`](struct.Owner.html#method.set_active_account) method.
|
||||
/// If None, the transaction will use the active account.
|
||||
/// * `amount` - The amount to send, in nanogrins. (`1 G = 1_000_000_000nG`)
|
||||
/// * `minimum_confirmations` - The minimum number of confirmations an output
|
||||
/// should have in order to be included in the transaction.
|
||||
/// * `max_outputs` - By default, the wallet selects as many inputs as possible in a
|
||||
/// transaction, to reduce the Output set and the fees. The wallet will attempt to spend
|
||||
/// include up to `max_outputs` in a transaction, however if this is not enough to cover
|
||||
/// the whole amount, the wallet will include more outputs. This parameter should be considered
|
||||
/// a soft limit.
|
||||
/// * `num_change_outputs` - The target number of change outputs to create in the transaction.
|
||||
/// The actual number created will be `num_change_outputs` + whatever remainder is needed.
|
||||
/// * `selection_strategy_is_use_all` - If `true`, attempt to use up as many outputs as
|
||||
/// possible to create the transaction, up the 'soft limit' of `max_outputs`. This helps
|
||||
/// to reduce the size of the UTXO set and the amount of data stored in the wallet, and
|
||||
/// minimizes fees. This will generally result in many inputs and a large change output(s),
|
||||
/// usually much larger than the amount being sent. If `false`, the transaction will include
|
||||
/// as many outputs as are needed to meet the amount, (and no more) starting with the smallest
|
||||
/// value outputs.
|
||||
/// * `message` - An optional participant message to include alongside the sender's public
|
||||
/// ParticipantData within the slate. This message will include a signature created with the
|
||||
/// sender's private excess value, and will be publically verifiable. Note this message is for
|
||||
/// the convenience of the participants during the exchange; it is not included in the final
|
||||
/// transaction sent to the chain. The message will be truncated to 256 characters.
|
||||
/// Validation of this message is optional.
|
||||
/// * `target_slate_version` Optionally set the output target slate version (acceptable
|
||||
/// down to the minimum slate version compatible with the current. If `None` the slate
|
||||
/// is generated with the latest version.
|
||||
/// * `args` - [`InitTxArgs`](../grin_wallet_libwallet/types/struct.InitTxArgs.html),
|
||||
/// transaction initialization arguments. See struct documentation for further detail.
|
||||
///
|
||||
/// # Returns
|
||||
/// * a result containing:
|
||||
|
@ -486,111 +465,69 @@ where
|
|||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let amount = 2_000_000_000;
|
||||
///
|
||||
/// // Attempt to create a transaction using the 'default' account
|
||||
/// let args = InitTxArgs {
|
||||
/// src_acct_name: None,
|
||||
/// amount: 2_000_000_000,
|
||||
/// minimum_confirmations: 2,
|
||||
/// max_outputs: 500,
|
||||
/// num_change_outputs: 1,
|
||||
/// selection_strategy_is_use_all: true,
|
||||
/// message: Some("Have some Grins. Love, Yeastplume".to_owned()),
|
||||
/// ..Default::default()
|
||||
/// };
|
||||
/// let result = api_owner.initiate_tx(
|
||||
/// None,
|
||||
/// amount, // amount
|
||||
/// 10, // minimum confirmations
|
||||
/// 500, // max outputs
|
||||
/// 1, // num change outputs
|
||||
/// true, // select all outputs
|
||||
/// Some("Have some Grins. Love, Yeastplume".to_owned()),
|
||||
/// None, // Use the default slate version
|
||||
/// );
|
||||
/// args,
|
||||
/// );
|
||||
///
|
||||
/// if let Ok(slate) = result {
|
||||
/// // Send slate somehow
|
||||
/// // ...
|
||||
/// // Lock our outputs if we're happy the slate was (or is being) sent
|
||||
/// api_owner.tx_lock_outputs(&slate);
|
||||
/// // Send slate somehow
|
||||
/// // ...
|
||||
/// // Lock our outputs if we're happy the slate was (or is being) sent
|
||||
/// api_owner.tx_lock_outputs(&slate);
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
pub fn initiate_tx(
|
||||
&self,
|
||||
src_acct_name: Option<&str>,
|
||||
amount: u64,
|
||||
minimum_confirmations: u64,
|
||||
max_outputs: usize,
|
||||
num_change_outputs: usize,
|
||||
selection_strategy_is_use_all: bool,
|
||||
message: Option<String>,
|
||||
target_slate_version: Option<u16>,
|
||||
) -> Result<Slate, Error> {
|
||||
let mut w = self.wallet.lock();
|
||||
w.open_with_credentials()?;
|
||||
let res = owner::initiate_tx(
|
||||
&mut *w,
|
||||
src_acct_name,
|
||||
amount,
|
||||
minimum_confirmations,
|
||||
max_outputs,
|
||||
num_change_outputs,
|
||||
selection_strategy_is_use_all,
|
||||
message,
|
||||
target_slate_version,
|
||||
self.doctest_mode,
|
||||
);
|
||||
w.close()?;
|
||||
res
|
||||
}
|
||||
pub fn initiate_tx(&self, args: InitTxArgs) -> Result<Slate, Error> {
|
||||
let send_args = args.send_args.clone();
|
||||
let mut slate = {
|
||||
let mut w = self.wallet.lock();
|
||||
w.open_with_credentials()?;
|
||||
let slate = owner::initiate_tx(&mut *w, args, self.doctest_mode)?;
|
||||
w.close()?;
|
||||
slate
|
||||
};
|
||||
// Helper functionality. If send arguments exist, attempt to send
|
||||
match send_args {
|
||||
Some(sa) => {
|
||||
match sa.method.as_ref() {
|
||||
"http" => {
|
||||
slate = HTTPWalletCommAdapter::new().send_tx_sync(&sa.dest, &slate)?
|
||||
}
|
||||
"keybase" => {
|
||||
//TODO: in case of keybase, the response might take 60s and leave the service hanging
|
||||
slate = KeybaseWalletCommAdapter::new().send_tx_sync(&sa.dest, &slate)?;
|
||||
}
|
||||
_ => {
|
||||
error!("unsupported payment method: {}", sa.method);
|
||||
return Err(ErrorKind::ClientCallback(
|
||||
"unsupported payment method".to_owned(),
|
||||
))?;
|
||||
}
|
||||
}
|
||||
self.tx_lock_outputs(&slate)?;
|
||||
let slate = match sa.finalize {
|
||||
true => self.finalize_tx(&slate)?,
|
||||
false => slate,
|
||||
};
|
||||
|
||||
/// Estimates the amount to be locked and fee for the transaction without creating one.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * As found in [`initiate_tx`](struct.Owner.html#method.initiate_tx) above.
|
||||
///
|
||||
/// # Returns
|
||||
/// * a result containing a
|
||||
/// [`TxEstimation`](../grin_wallet_libwallet/types/struct.TxEstimation.html)
|
||||
///
|
||||
/// # Example
|
||||
/// Set up as in [new](struct.Owner.html#method.new) method above.
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let amount = 2_000_000_000;
|
||||
///
|
||||
/// // Estimate transaction using default account
|
||||
/// let result = api_owner.estimate_initiate_tx(
|
||||
/// None,
|
||||
/// amount, // amount
|
||||
/// 10, // minimum confirmations
|
||||
/// 500, // max outputs
|
||||
/// 1, // num change outputs
|
||||
/// true, // select all outputs
|
||||
/// );
|
||||
///
|
||||
/// if let Ok(est) = result {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
pub fn estimate_initiate_tx(
|
||||
&self,
|
||||
src_acct_name: Option<&str>,
|
||||
amount: u64,
|
||||
minimum_confirmations: u64,
|
||||
max_outputs: usize,
|
||||
num_change_outputs: usize,
|
||||
selection_strategy_is_use_all: bool,
|
||||
) -> Result<TxEstimation, Error> {
|
||||
let mut w = self.wallet.lock();
|
||||
w.open_with_credentials()?;
|
||||
let res = owner::estimate_initiate_tx(
|
||||
&mut *w,
|
||||
src_acct_name,
|
||||
amount,
|
||||
minimum_confirmations,
|
||||
max_outputs,
|
||||
num_change_outputs,
|
||||
selection_strategy_is_use_all,
|
||||
);
|
||||
w.close()?;
|
||||
res
|
||||
if sa.post_tx {
|
||||
self.post_tx(&slate.tx, sa.fluff)?;
|
||||
}
|
||||
Ok(slate)
|
||||
}
|
||||
None => Ok(slate),
|
||||
}
|
||||
}
|
||||
|
||||
/// Locks the outputs associated with the inputs to the transaction in the given
|
||||
|
@ -621,19 +558,19 @@ where
|
|||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let amount = 2_000_000_000;
|
||||
///
|
||||
/// // Attempt to create a transaction using the 'default' account
|
||||
/// let args = InitTxArgs {
|
||||
/// src_acct_name: None,
|
||||
/// amount: 2_000_000_000,
|
||||
/// minimum_confirmations: 10,
|
||||
/// max_outputs: 500,
|
||||
/// num_change_outputs: 1,
|
||||
/// selection_strategy_is_use_all: true,
|
||||
/// message: Some("Remember to lock this when we're happy this is sent".to_owned()),
|
||||
/// ..Default::default()
|
||||
/// };
|
||||
/// let result = api_owner.initiate_tx(
|
||||
/// None,
|
||||
/// amount, // amount
|
||||
/// 10, // minimum confirmations
|
||||
/// 500, // max outputs
|
||||
/// 1, // num change outputs
|
||||
/// true, // select all outputs
|
||||
/// Some("Remember to lock when we're happy this is sent".to_owned()),
|
||||
/// None, // Use the default slate version
|
||||
/// );
|
||||
/// args,
|
||||
/// );
|
||||
///
|
||||
/// if let Ok(slate) = result {
|
||||
/// // Send slate somehow
|
||||
|
@ -679,19 +616,19 @@ where
|
|||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let amount = 2_000_000_000;
|
||||
///
|
||||
/// // Attempt to create a transaction using the 'default' account
|
||||
/// let args = InitTxArgs {
|
||||
/// src_acct_name: None,
|
||||
/// amount: 2_000_000_000,
|
||||
/// minimum_confirmations: 10,
|
||||
/// max_outputs: 500,
|
||||
/// num_change_outputs: 1,
|
||||
/// selection_strategy_is_use_all: true,
|
||||
/// message: Some("Finalize this tx now".to_owned()),
|
||||
/// ..Default::default()
|
||||
/// };
|
||||
/// let result = api_owner.initiate_tx(
|
||||
/// None,
|
||||
/// amount, // amount
|
||||
/// 10, // minimum confirmations
|
||||
/// 500, // max outputs
|
||||
/// 1, // num change outputs
|
||||
/// true, // select all outputs
|
||||
/// Some("Finalize this tx now".to_owned()),
|
||||
/// None, // Use the default slate version
|
||||
/// );
|
||||
/// args,
|
||||
/// );
|
||||
///
|
||||
/// if let Ok(slate) = result {
|
||||
/// // Send slate somehow
|
||||
|
@ -736,19 +673,19 @@ where
|
|||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let amount = 2_000_000_000;
|
||||
///
|
||||
/// // Attempt to create a transaction using the 'default' account
|
||||
/// let args = InitTxArgs {
|
||||
/// src_acct_name: None,
|
||||
/// amount: 2_000_000_000,
|
||||
/// minimum_confirmations: 10,
|
||||
/// max_outputs: 500,
|
||||
/// num_change_outputs: 1,
|
||||
/// selection_strategy_is_use_all: true,
|
||||
/// message: Some("Post this tx".to_owned()),
|
||||
/// ..Default::default()
|
||||
/// };
|
||||
/// let result = api_owner.initiate_tx(
|
||||
/// None,
|
||||
/// amount, // amount
|
||||
/// 10, // minimum confirmations
|
||||
/// 500, // max outputs
|
||||
/// 1, // num change outputs
|
||||
/// true, // select all outputs
|
||||
/// Some("Finalize this tx now".to_owned()),
|
||||
/// None, // Use the default slate version
|
||||
/// );
|
||||
/// args,
|
||||
/// );
|
||||
///
|
||||
/// if let Ok(slate) = result {
|
||||
/// // Send slate somehow
|
||||
|
@ -797,19 +734,19 @@ where
|
|||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let amount = 2_000_000_000;
|
||||
///
|
||||
/// // Attempt to create a transaction using the 'default' account
|
||||
/// let args = InitTxArgs {
|
||||
/// src_acct_name: None,
|
||||
/// amount: 2_000_000_000,
|
||||
/// minimum_confirmations: 10,
|
||||
/// max_outputs: 500,
|
||||
/// num_change_outputs: 1,
|
||||
/// selection_strategy_is_use_all: true,
|
||||
/// message: Some("Cancel this tx".to_owned()),
|
||||
/// ..Default::default()
|
||||
/// };
|
||||
/// let result = api_owner.initiate_tx(
|
||||
/// None,
|
||||
/// amount, // amount
|
||||
/// 10, // minimum confirmations
|
||||
/// 500, // max outputs
|
||||
/// 1, // num change outputs
|
||||
/// true, // select all outputs
|
||||
/// Some("Cancel this tx".to_owned()),
|
||||
/// None, // Use the default slate version
|
||||
/// );
|
||||
/// args,
|
||||
/// );
|
||||
///
|
||||
/// if let Ok(slate) = result {
|
||||
/// // Send slate somehow
|
||||
|
@ -890,19 +827,19 @@ where
|
|||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let amount = 2_000_000_000;
|
||||
///
|
||||
/// // Attempt to create a transaction using the 'default' account
|
||||
/// let args = InitTxArgs {
|
||||
/// src_acct_name: None,
|
||||
/// amount: 2_000_000_000,
|
||||
/// minimum_confirmations: 10,
|
||||
/// max_outputs: 500,
|
||||
/// num_change_outputs: 1,
|
||||
/// selection_strategy_is_use_all: true,
|
||||
/// message: Some("Just verify messages".to_owned()),
|
||||
/// ..Default::default()
|
||||
/// };
|
||||
/// let result = api_owner.initiate_tx(
|
||||
/// None,
|
||||
/// amount, // amount
|
||||
/// 10, // minimum confirmations
|
||||
/// 500, // max outputs
|
||||
/// 1, // num change outputs
|
||||
/// true, // select all outputs
|
||||
/// Some("Finalize this tx now".to_owned()),
|
||||
/// None, // Use the default slate version
|
||||
/// );
|
||||
/// args,
|
||||
/// );
|
||||
///
|
||||
/// if let Ok(slate) = result {
|
||||
/// // Send slate somehow
|
||||
|
@ -919,8 +856,40 @@ where
|
|||
owner::verify_slate_messages(slate)
|
||||
}
|
||||
|
||||
/// Attempt to restore contents of wallet
|
||||
/// TODO: Full docs
|
||||
/// Scans the entire UTXO set from the node, creating outputs for each scanned
|
||||
/// output that matches the wallet's master seed. This function is intended to be called as part
|
||||
/// of a recovery process (either from BIP32 phrase or backup seed files,) and will error if the
|
||||
/// wallet is non-empty, i.e. contains any outputs at all.
|
||||
///
|
||||
/// This operation scans the entire chain, and is expected to be time intensive. It is imperative
|
||||
/// that no other processes should be trying to use the wallet at the same time this function is
|
||||
/// running.
|
||||
///
|
||||
/// A single [TxLogEntry](../grin_wallet_libwallet/types/struct.TxLogEntry.html) is created for
|
||||
/// all non-coinbase outputs discovered and restored during this process. A separate entry
|
||||
/// is created for each coinbase output.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * None
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Ok(())` if successful
|
||||
/// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered.
|
||||
|
||||
/// # Example
|
||||
/// Set up as in [`new`](struct.Owner.html#method.new) method above.
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let result = api_owner.restore();
|
||||
///
|
||||
/// if let Ok(_) = result {
|
||||
/// // Wallet outputs should be consistent with what's on chain
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
pub fn restore(&self) -> Result<(), Error> {
|
||||
let mut w = self.wallet.lock();
|
||||
w.open_with_credentials()?;
|
||||
|
@ -929,8 +898,52 @@ where
|
|||
res
|
||||
}
|
||||
|
||||
/// Attempt to check and fix the contents of the wallet
|
||||
/// TODO: Full docs
|
||||
/// Scans the entire UTXO set from the node, identify which outputs belong to the given wallet
|
||||
/// update the wallet state to be consistent with what's currently in the UTXO set.
|
||||
///
|
||||
/// This function can be used to repair wallet state, particularly by restoring outputs that may
|
||||
/// be missing if the wallet owner has cancelled transactions locally that were then successfully
|
||||
/// posted to the chain.
|
||||
///
|
||||
/// This operation scans the entire chain, and is expected to be time intensive. It is imperative
|
||||
/// that no other processes should be trying to use the wallet at the same time this function is
|
||||
/// running.
|
||||
///
|
||||
/// When an output is found that doesn't exist in the wallet, a corresponding
|
||||
/// [TxLogEntry](../grin_wallet_libwallet/types/struct.TxLogEntry.html) is created.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `delete_unconfirmed` - if `false`, the check_repair process will be non-destructive, and
|
||||
/// mostly limited to restoring missing outputs. It will leave unconfirmed transaction logs entries
|
||||
/// and unconfirmed outputs intact. If `true`, the process will unlock all locked outputs,
|
||||
/// restore all missing outputs, and mark any outputs that have been marked 'Spent' but are still
|
||||
/// in the UTXO set as 'Unspent' (as can happen during a fork). It will also attempt to cancel any
|
||||
/// transaction log entries associated with any locked outputs or outputs incorrectly marked 'Spent'.
|
||||
/// Note this completely removes all outstanding transactions, so users should be very aware what
|
||||
/// will happen if this flag is set. Note that if transactions/outputs are removed that later
|
||||
/// confirm on the chain, another call to this function will restore them.
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Ok(())` if successful
|
||||
/// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered.
|
||||
|
||||
/// # Example
|
||||
/// Set up as in [`new`](struct.Owner.html#method.new) method above.
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let result = api_owner.check_repair(
|
||||
/// false,
|
||||
/// );
|
||||
///
|
||||
/// if let Ok(_) = result {
|
||||
/// // Wallet outputs should be consistent with what's on chain
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
pub fn check_repair(&self, delete_unconfirmed: bool) -> Result<(), Error> {
|
||||
let mut w = self.wallet.lock();
|
||||
w.open_with_credentials()?;
|
||||
|
@ -939,9 +952,44 @@ where
|
|||
res
|
||||
}
|
||||
|
||||
/// Retrieve current height from node
|
||||
// TODO: Should return u64 as string
|
||||
pub fn node_height(&self) -> Result<(u64, bool), Error> {
|
||||
/// Retrieves the last known height known by the wallet. This is determined as follows:
|
||||
/// * If the wallet can successfully contact its configured node, the reported node
|
||||
/// height is returned, and the `updated_from_node` field in the response is `true`
|
||||
/// * If the wallet cannot contact the node, this function returns the maximum height
|
||||
/// of all outputs contained within the wallet, and the `updated_from_node` fields
|
||||
/// in the response is set to false.
|
||||
///
|
||||
/// Clients should generally ensure the `updated_from_node` field is returned as
|
||||
/// `true` before assuming the height for any operation.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * None
|
||||
///
|
||||
/// # Returns
|
||||
/// * Ok with a [`NodeHeightResult`](../grin_wallet_libwallet/types/struct.NodeHeightResult.html)
|
||||
/// if successful. If the height result was obtained from the configured node,
|
||||
/// `updated_from_node` will be set to `true`
|
||||
/// * or [`libwallet::Error`](../grin_wallet_libwallet/struct.Error.html) if an error is encountered.
|
||||
///
|
||||
/// # Example
|
||||
/// Set up as in [`new`](struct.Owner.html#method.new) method above.
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let result = api_owner.node_height();
|
||||
///
|
||||
/// if let Ok(node_height_result) = result {
|
||||
/// if node_height_result.updated_from_node {
|
||||
/// //we can assume node_height_result.height is relatively safe to use
|
||||
///
|
||||
/// }
|
||||
/// //...
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
pub fn node_height(&self) -> Result<NodeHeightResult, Error> {
|
||||
let mut w = self.wallet.lock();
|
||||
w.open_with_credentials()?;
|
||||
let res = owner::node_height(&mut *w);
|
||||
|
@ -970,7 +1018,7 @@ macro_rules! doctest_helper_setup_doc_env {
|
|||
use api::Owner;
|
||||
use config::WalletConfig;
|
||||
use impls::{HTTPNodeClient, LMDBBackend, WalletSeed};
|
||||
use libwallet::types::WalletBackend;
|
||||
use libwallet::types::{InitTxArgs, WalletBackend};
|
||||
|
||||
let dir = tempdir().map_err(|e| format!("{:#?}", e)).unwrap();
|
||||
let dir = dir
|
||||
|
|
|
@ -19,8 +19,8 @@ use crate::core::core::Transaction;
|
|||
use crate::keychain::{Identifier, Keychain};
|
||||
use crate::libwallet::slate::Slate;
|
||||
use crate::libwallet::types::{
|
||||
AcctPathMapping, NodeClient, OutputCommitMapping, TxEstimation, TxLogEntry, WalletBackend,
|
||||
WalletInfo,
|
||||
AcctPathMapping, InitTxArgs, NodeClient, NodeHeightResult, OutputCommitMapping, TxLogEntry,
|
||||
WalletBackend, WalletInfo,
|
||||
};
|
||||
use crate::libwallet::ErrorKind;
|
||||
use crate::Owner;
|
||||
|
@ -321,7 +321,19 @@ pub trait OwnerRpc {
|
|||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "initiate_tx",
|
||||
"params": [null, 6000000000, 2, 500, 1, true, "my message", null],
|
||||
"params": {
|
||||
"args": {
|
||||
"src_acct_name": null,
|
||||
"amount": "6000000000",
|
||||
"minimum_confirmations": 2,
|
||||
"max_outputs": 500,
|
||||
"num_change_outputs": 1,
|
||||
"selection_strategy_is_use_all": true,
|
||||
"message": "my message",
|
||||
"target_slate_version": null,
|
||||
"send_args": null
|
||||
}
|
||||
},
|
||||
"id": 1
|
||||
}
|
||||
# "#
|
||||
|
@ -388,62 +400,11 @@ pub trait OwnerRpc {
|
|||
```
|
||||
*/
|
||||
|
||||
fn initiate_tx(
|
||||
&self,
|
||||
src_acct_name: Option<String>,
|
||||
amount: u64,
|
||||
minimum_confirmations: u64,
|
||||
max_outputs: usize,
|
||||
num_change_outputs: usize,
|
||||
selection_strategy_is_use_all: bool,
|
||||
message: Option<String>,
|
||||
target_slate_version: Option<u16>,
|
||||
) -> Result<Slate, ErrorKind>;
|
||||
|
||||
/**
|
||||
Networked version of [Owner::estimate_initiate_tx](struct.Owner.html#method.estimate_initiate_tx).
|
||||
|
||||
|
||||
```
|
||||
# grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!(
|
||||
# r#"
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "estimate_initiate_tx",
|
||||
"params": [null, 6000000000, 2, 500, 1, true],
|
||||
"id": 1
|
||||
}
|
||||
# "#
|
||||
# ,
|
||||
# r#"
|
||||
{
|
||||
"id": 1,
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"Ok": {
|
||||
"total": "60000000000",
|
||||
"fee": "8000000"
|
||||
}
|
||||
}
|
||||
}
|
||||
# "#
|
||||
# ,4, false, false, false);
|
||||
```
|
||||
*/
|
||||
fn estimate_initiate_tx(
|
||||
&self,
|
||||
src_acct_name: Option<String>,
|
||||
amount: u64,
|
||||
minimum_confirmations: u64,
|
||||
max_outputs: usize,
|
||||
num_change_outputs: usize,
|
||||
selection_strategy_is_use_all: bool,
|
||||
) -> Result<TxEstimation, ErrorKind>;
|
||||
fn initiate_tx(&self, args: InitTxArgs) -> Result<Slate, ErrorKind>;
|
||||
|
||||
/**
|
||||
Networked version of [Owner::tx_lock_outputs](struct.Owner.html#method.tx_lock_outputs).
|
||||
|
||||
|
||||
```
|
||||
# grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!(
|
||||
# r#"
|
||||
|
@ -1029,17 +990,17 @@ pub trait OwnerRpc {
|
|||
"id": 1,
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"Ok": [
|
||||
5,
|
||||
true
|
||||
]
|
||||
"Ok": {
|
||||
"height": "5",
|
||||
"updated_from_node": true
|
||||
}
|
||||
}
|
||||
}
|
||||
# "#
|
||||
# , 5, false, false, false);
|
||||
```
|
||||
*/
|
||||
fn node_height(&self) -> Result<(u64, bool), ErrorKind>;
|
||||
fn node_height(&self) -> Result<NodeHeightResult, ErrorKind>;
|
||||
}
|
||||
|
||||
impl<W: ?Sized, C, K> OwnerRpc for Owner<W, C, K>
|
||||
|
@ -1087,50 +1048,8 @@ where
|
|||
.map_err(|e| e.kind())
|
||||
}
|
||||
|
||||
fn initiate_tx(
|
||||
&self,
|
||||
src_acct_name: Option<String>,
|
||||
amount: u64,
|
||||
minimum_confirmations: u64,
|
||||
max_outputs: usize,
|
||||
num_change_outputs: usize,
|
||||
selection_strategy_is_use_all: bool,
|
||||
message: Option<String>,
|
||||
target_slate_version: Option<u16>,
|
||||
) -> Result<Slate, ErrorKind> {
|
||||
Owner::initiate_tx(
|
||||
self,
|
||||
src_acct_name.as_ref().map(String::as_str),
|
||||
amount,
|
||||
minimum_confirmations,
|
||||
max_outputs,
|
||||
num_change_outputs,
|
||||
selection_strategy_is_use_all,
|
||||
message,
|
||||
target_slate_version,
|
||||
)
|
||||
.map_err(|e| e.kind())
|
||||
}
|
||||
|
||||
fn estimate_initiate_tx(
|
||||
&self,
|
||||
src_acct_name: Option<String>,
|
||||
amount: u64,
|
||||
minimum_confirmations: u64,
|
||||
max_outputs: usize,
|
||||
num_change_outputs: usize,
|
||||
selection_strategy_is_use_all: bool,
|
||||
) -> Result<TxEstimation, ErrorKind> {
|
||||
Owner::estimate_initiate_tx(
|
||||
self,
|
||||
src_acct_name.as_ref().map(String::as_str),
|
||||
amount,
|
||||
minimum_confirmations,
|
||||
max_outputs,
|
||||
num_change_outputs,
|
||||
selection_strategy_is_use_all,
|
||||
)
|
||||
.map_err(|e| e.kind())
|
||||
fn initiate_tx(&self, args: InitTxArgs) -> Result<Slate, ErrorKind> {
|
||||
Owner::initiate_tx(self, args).map_err(|e| e.kind())
|
||||
}
|
||||
|
||||
fn finalize_tx(&self, mut slate: Slate) -> Result<Slate, ErrorKind> {
|
||||
|
@ -1165,7 +1084,7 @@ where
|
|||
Owner::check_repair(self, delete_unconfirmed).map_err(|e| e.kind())
|
||||
}
|
||||
|
||||
fn node_height(&self) -> Result<(u64, bool), ErrorKind> {
|
||||
fn node_height(&self) -> Result<NodeHeightResult, ErrorKind> {
|
||||
Owner::node_height(self).map_err(|e| e.kind())
|
||||
}
|
||||
}
|
||||
|
@ -1244,16 +1163,16 @@ pub fn run_doctest_owner(
|
|||
let amount = 60_000_000_000;
|
||||
let mut w = wallet1.lock();
|
||||
w.open_with_credentials().unwrap();
|
||||
let mut slate = api_impl::owner::initiate_tx(
|
||||
&mut *w, None, // account
|
||||
amount, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None, None, true,
|
||||
)
|
||||
.unwrap();
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let mut slate = api_impl::owner::initiate_tx(&mut *w, args, true).unwrap();
|
||||
{
|
||||
let mut w2 = wallet2.lock();
|
||||
w2.open_with_credentials().unwrap();
|
||||
|
|
|
@ -35,7 +35,7 @@ use crate::impls::{
|
|||
LMDBBackend, NullWalletCommAdapter,
|
||||
};
|
||||
use crate::impls::{HTTPNodeClient, WalletSeed};
|
||||
use crate::libwallet::types::{NodeClient, WalletInst};
|
||||
use crate::libwallet::types::{InitTxArgs, NodeClient, WalletInst};
|
||||
use crate::{controller, display};
|
||||
|
||||
/// Arguments common to all wallet commands
|
||||
|
@ -247,31 +247,35 @@ pub fn send(
|
|||
let strategies = vec!["smallest", "all"]
|
||||
.into_iter()
|
||||
.map(|strategy| {
|
||||
let est = api
|
||||
.estimate_initiate_tx(
|
||||
None,
|
||||
args.amount,
|
||||
args.minimum_confirmations,
|
||||
args.max_outputs,
|
||||
args.change_outputs,
|
||||
strategy == "all",
|
||||
)
|
||||
.unwrap();
|
||||
(strategy, est.total, est.fee)
|
||||
let init_args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: args.amount,
|
||||
minimum_confirmations: args.minimum_confirmations,
|
||||
max_outputs: args.max_outputs as u32,
|
||||
num_change_outputs: args.change_outputs as u32,
|
||||
selection_strategy_is_use_all: strategy == "all",
|
||||
estimate_only: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
let slate = api.initiate_tx(init_args).unwrap();
|
||||
(strategy, slate.amount, slate.fee)
|
||||
})
|
||||
.collect();
|
||||
display::estimate(args.amount, strategies, dark_scheme);
|
||||
} else {
|
||||
let result = api.initiate_tx(
|
||||
None,
|
||||
args.amount,
|
||||
args.minimum_confirmations,
|
||||
args.max_outputs,
|
||||
args.change_outputs,
|
||||
args.selection_strategy == "all",
|
||||
args.message.clone(),
|
||||
args.target_slate_version,
|
||||
);
|
||||
let init_args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: args.amount,
|
||||
minimum_confirmations: args.minimum_confirmations,
|
||||
max_outputs: args.max_outputs as u32,
|
||||
num_change_outputs: args.change_outputs as u32,
|
||||
selection_strategy_is_use_all: args.selection_strategy == "all",
|
||||
message: args.message.clone(),
|
||||
target_slate_version: args.target_slate_version,
|
||||
send_args: None,
|
||||
..Default::default()
|
||||
};
|
||||
let result = api.initiate_tx(init_args);
|
||||
let mut slate = match result {
|
||||
Ok(s) => {
|
||||
info!(
|
||||
|
@ -421,9 +425,9 @@ pub fn outputs(
|
|||
dark_scheme: bool,
|
||||
) -> Result<(), Error> {
|
||||
controller::owner_single_use(wallet.clone(), |api| {
|
||||
let (height, _) = api.node_height()?;
|
||||
let res = api.node_height()?;
|
||||
let (validated, outputs) = api.retrieve_outputs(g_args.show_spent, true, None)?;
|
||||
display::outputs(&g_args.account, height, validated, outputs, dark_scheme)?;
|
||||
display::outputs(&g_args.account, res.height, validated, outputs, dark_scheme)?;
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(())
|
||||
|
@ -441,12 +445,12 @@ pub fn txs(
|
|||
dark_scheme: bool,
|
||||
) -> Result<(), Error> {
|
||||
controller::owner_single_use(wallet.clone(), |api| {
|
||||
let (height, _) = api.node_height()?;
|
||||
let res = api.node_height()?;
|
||||
let (validated, txs) = api.retrieve_txs(true, args.id, None)?;
|
||||
let include_status = !args.id.is_some();
|
||||
display::txs(
|
||||
&g_args.account,
|
||||
height,
|
||||
res.height,
|
||||
validated,
|
||||
&txs,
|
||||
include_status,
|
||||
|
@ -456,7 +460,7 @@ pub fn txs(
|
|||
// inputs/outputs and messages
|
||||
if args.id.is_some() {
|
||||
let (_, outputs) = api.retrieve_outputs(true, false, args.id)?;
|
||||
display::outputs(&g_args.account, height, validated, outputs, dark_scheme)?;
|
||||
display::outputs(&g_args.account, res.height, validated, outputs, dark_scheme)?;
|
||||
// should only be one here, but just in case
|
||||
for tx in txs {
|
||||
display::tx_messages(&tx, dark_scheme)?;
|
||||
|
|
|
@ -23,7 +23,8 @@ use crate::impls::{FileWalletCommAdapter, HTTPWalletCommAdapter, KeybaseWalletCo
|
|||
use crate::keychain::Keychain;
|
||||
use crate::libwallet::slate::Slate;
|
||||
use crate::libwallet::types::{
|
||||
CbData, NodeClient, OutputCommitMapping, SendTXArgs, TxLogEntry, WalletBackend, WalletInfo,
|
||||
CbData, InitTxArgs, NodeClient, OutputCommitMapping, SendTXArgs, TxLogEntry, WalletBackend,
|
||||
WalletInfo,
|
||||
};
|
||||
use crate::libwallet::{Error, ErrorKind};
|
||||
use crate::util::to_base64;
|
||||
|
@ -289,7 +290,8 @@ where
|
|||
_req: &Request<Body>,
|
||||
api: Owner<T, C, K>,
|
||||
) -> Result<(u64, bool), Error> {
|
||||
api.node_height()
|
||||
let res = api.node_height()?;
|
||||
Ok((res.height, res.updated_from_node))
|
||||
}
|
||||
|
||||
fn handle_get_request(&self, req: &Request<Body>) -> Result<Response<Body>, Error> {
|
||||
|
@ -299,7 +301,7 @@ where
|
|||
match req
|
||||
.uri()
|
||||
.path()
|
||||
.trim_right_matches("/")
|
||||
.trim_end_matches("/")
|
||||
.rsplit("/")
|
||||
.next()
|
||||
.unwrap()
|
||||
|
@ -320,16 +322,19 @@ where
|
|||
api: Owner<T, C, K>,
|
||||
) -> Box<dyn Future<Item = Slate, Error = Error> + Send> {
|
||||
Box::new(parse_body(req).and_then(move |args: SendTXArgs| {
|
||||
let result = api.initiate_tx(
|
||||
None,
|
||||
args.amount,
|
||||
args.minimum_confirmations,
|
||||
args.max_outputs,
|
||||
args.num_change_outputs,
|
||||
args.selection_strategy_is_use_all,
|
||||
args.message,
|
||||
args.target_slate_version,
|
||||
);
|
||||
let init_args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: args.amount,
|
||||
minimum_confirmations: args.minimum_confirmations,
|
||||
max_outputs: args.max_outputs as u32,
|
||||
num_change_outputs: args.num_change_outputs as u32,
|
||||
selection_strategy_is_use_all: args.selection_strategy_is_use_all,
|
||||
message: args.message.clone(),
|
||||
target_slate_version: args.target_slate_version,
|
||||
send_args: None,
|
||||
..Default::default()
|
||||
};
|
||||
let result = api.initiate_tx(init_args);
|
||||
let mut slate = match result {
|
||||
Ok(s) => {
|
||||
info!(
|
||||
|
@ -554,7 +559,7 @@ where
|
|||
match req
|
||||
.uri()
|
||||
.path()
|
||||
.trim_right_matches("/")
|
||||
.trim_end_matches("/")
|
||||
.rsplit("/")
|
||||
.next()
|
||||
.unwrap()
|
||||
|
@ -688,7 +693,7 @@ where
|
|||
match req
|
||||
.uri()
|
||||
.path()
|
||||
.trim_right_matches("/")
|
||||
.trim_end_matches("/")
|
||||
.rsplit("/")
|
||||
.next()
|
||||
.unwrap()
|
||||
|
|
|
@ -26,6 +26,7 @@ use self::core::global::ChainTypes;
|
|||
use self::keychain::{ExtKeychain, Keychain};
|
||||
use grin_wallet_libwallet as libwallet;
|
||||
use impls::test_framework::{self, LocalWalletClient, WalletProxy};
|
||||
use libwallet::types::InitTxArgs;
|
||||
use std::fs;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
@ -179,14 +180,16 @@ fn accounts_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
}
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
let mut slate = api.initiate_tx(
|
||||
None, reward, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None, None,
|
||||
)?;
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: reward,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let mut slate = api.initiate_tx(args)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate)?;
|
||||
api.tx_lock_outputs(&slate)?;
|
||||
slate = api.finalize_tx(&slate)?;
|
||||
|
|
|
@ -28,7 +28,7 @@ use self::keychain::ExtKeychain;
|
|||
use grin_wallet_libwallet as libwallet;
|
||||
use impls::test_framework::{self, LocalWalletClient, WalletProxy};
|
||||
use impls::FileWalletCommAdapter;
|
||||
use libwallet::types::WalletInst;
|
||||
use libwallet::types::{InitTxArgs, WalletInst};
|
||||
use std::fs;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
@ -178,16 +178,16 @@ fn check_repair_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
// perform a transaction, but don't let it finish
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||
// send to send
|
||||
let mut slate = api.initiate_tx(
|
||||
None,
|
||||
reward * 2, // amount
|
||||
cm, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None, // optional message
|
||||
None,
|
||||
)?;
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: reward * 2,
|
||||
minimum_confirmations: cm,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let mut slate = api.initiate_tx(args)?;
|
||||
// output tx file
|
||||
let file_adapter = FileWalletCommAdapter::new();
|
||||
let send_file = format!("{}/part_tx_1.tx", test_dir);
|
||||
|
|
|
@ -31,6 +31,8 @@ use std::fs;
|
|||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use grin_wallet_libwallet::types::InitTxArgs;
|
||||
|
||||
use serde_json;
|
||||
|
||||
fn clean_output_dir(test_dir: &str) {
|
||||
|
@ -105,16 +107,17 @@ fn file_exchange_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.total, bh * reward);
|
||||
// send to send
|
||||
let mut slate = api.initiate_tx(
|
||||
Some("mining"),
|
||||
reward * 2, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
Some(message.to_owned()), // optional message
|
||||
None,
|
||||
)?;
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: Some("mining".to_owned()),
|
||||
amount: reward * 2,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
message: Some(message.to_owned()),
|
||||
..Default::default()
|
||||
};
|
||||
let mut slate = api.initiate_tx(args)?;
|
||||
// output tx file
|
||||
let file_adapter = FileWalletCommAdapter::new();
|
||||
file_adapter.send_tx_async(&send_file, &mut slate)?;
|
||||
|
|
|
@ -26,6 +26,7 @@ use self::core::global;
|
|||
use self::core::global::ChainTypes;
|
||||
use self::keychain::ExtKeychain;
|
||||
use self::libwallet::slate::Slate;
|
||||
use self::libwallet::types::InitTxArgs;
|
||||
use impls::test_framework::{self, LocalWalletClient, WalletProxy};
|
||||
use impls::FileWalletCommAdapter;
|
||||
use std::fs;
|
||||
|
@ -103,16 +104,16 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.total, bh * reward);
|
||||
// send to send
|
||||
let mut slate = api.initiate_tx(
|
||||
Some("mining"),
|
||||
reward * 2, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: Some("mining".to_owned()),
|
||||
amount: reward * 2,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let mut slate = api.initiate_tx(args)?;
|
||||
// output tx file
|
||||
let file_adapter = FileWalletCommAdapter::new();
|
||||
file_adapter.send_tx_async(&send_file, &mut slate)?;
|
||||
|
@ -200,16 +201,16 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let slate_i = sender_api.initiate_tx(
|
||||
None,
|
||||
amount * 2, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: reward * 2,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = sender_api.initiate_tx(args)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate)?;
|
||||
slate = sender_api.finalize_tx(&mut slate)?;
|
||||
|
|
|
@ -26,7 +26,7 @@ use self::core::global;
|
|||
use self::core::global::ChainTypes;
|
||||
use self::keychain::{ExtKeychain, Identifier, Keychain};
|
||||
use self::libwallet::slate::Slate;
|
||||
use self::libwallet::types::AcctPathMapping;
|
||||
use self::libwallet::types::{AcctPathMapping, InitTxArgs};
|
||||
use impls::test_framework::{self, LocalWalletClient, WalletProxy};
|
||||
use std::fs;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
@ -237,14 +237,16 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
let mut slate = Slate::blank(1);
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let slate_i = sender_api.initiate_tx(
|
||||
None, amount, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None, None,
|
||||
)?;
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: amount,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = sender_api.initiate_tx(args)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate)?;
|
||||
slate = sender_api.finalize_tx(&slate)?;
|
||||
|
@ -258,16 +260,16 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
// Send some to wallet 3
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let slate_i = sender_api.initiate_tx(
|
||||
None,
|
||||
amount * 2, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: amount * 2,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = sender_api.initiate_tx(args)?;
|
||||
slate = client1.send_tx_slate_direct("wallet3", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate)?;
|
||||
slate = sender_api.finalize_tx(&slate)?;
|
||||
|
@ -281,16 +283,16 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
// Wallet3 to wallet 2
|
||||
wallet::controller::owner_single_use(wallet3.clone(), |sender_api| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let slate_i = sender_api.initiate_tx(
|
||||
None,
|
||||
amount * 3, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: amount * 3,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = sender_api.initiate_tx(args)?;
|
||||
slate = client3.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate)?;
|
||||
slate = sender_api.finalize_tx(&slate)?;
|
||||
|
@ -310,16 +312,16 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
// Wallet3 to wallet 2 again (to another account)
|
||||
wallet::controller::owner_single_use(wallet3.clone(), |sender_api| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let slate_i = sender_api.initiate_tx(
|
||||
None,
|
||||
amount * 3, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: amount * 3,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = sender_api.initiate_tx(args)?;
|
||||
slate = client3.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate)?;
|
||||
slate = sender_api.finalize_tx(&slate)?;
|
||||
|
|
|
@ -26,6 +26,7 @@ use self::core::global::ChainTypes;
|
|||
use self::keychain::ExtKeychain;
|
||||
use grin_wallet_libwallet as libwallet;
|
||||
use impls::test_framework::{self, LocalWalletClient, WalletProxy};
|
||||
use libwallet::types::InitTxArgs;
|
||||
use std::fs;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
@ -86,16 +87,16 @@ fn self_send_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.total, bh * reward);
|
||||
// send to send
|
||||
let mut slate = api.initiate_tx(
|
||||
Some("mining"),
|
||||
reward * 2, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: Some("mining".to_owned()),
|
||||
amount: reward * 2,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let mut slate = api.initiate_tx(args)?;
|
||||
api.tx_lock_outputs(&slate)?;
|
||||
// Send directly to self
|
||||
wallet::controller::foreign_single_use(wallet1.clone(), |api| {
|
||||
|
|
|
@ -27,7 +27,7 @@ use self::core::global;
|
|||
use self::core::global::ChainTypes;
|
||||
use self::keychain::ExtKeychain;
|
||||
use self::libwallet::slate::Slate;
|
||||
use self::libwallet::types::OutputStatus;
|
||||
use self::libwallet::types::{InitTxArgs, OutputStatus};
|
||||
use impls::test_framework::{self, LocalWalletClient, WalletProxy};
|
||||
use std::fs;
|
||||
use std::thread;
|
||||
|
@ -100,14 +100,16 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
let mut slate = Slate::blank(1);
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let slate_i = sender_api.initiate_tx(
|
||||
None, amount, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None, None,
|
||||
)?;
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: amount,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = sender_api.initiate_tx(args)?;
|
||||
|
||||
// Check we are creating a tx with the expected lock_height of 0.
|
||||
// We will check this produces a Plain kernel later.
|
||||
|
@ -250,26 +252,32 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
|
||||
// Estimate fee and locked amount for a transaction
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
let est = sender_api.estimate_initiate_tx(
|
||||
None,
|
||||
amount * 2, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
)?;
|
||||
assert_eq!(est.total, 600_000_000_000);
|
||||
let init_args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: amount * 2,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
estimate_only: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
let est = sender_api.initiate_tx(init_args)?;
|
||||
assert_eq!(est.amount, 600_000_000_000);
|
||||
assert_eq!(est.fee, 4_000_000);
|
||||
|
||||
let est = sender_api.estimate_initiate_tx(
|
||||
None,
|
||||
amount * 2, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
false, // select the smallest amount of outputs
|
||||
)?;
|
||||
assert_eq!(est.total, 180_000_000_000);
|
||||
let init_args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: amount * 2,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: false, //select smallest number
|
||||
estimate_only: Some(true),
|
||||
..Default::default()
|
||||
};
|
||||
let est = sender_api.initiate_tx(init_args)?;
|
||||
assert_eq!(est.amount, 180_000_000_000);
|
||||
assert_eq!(est.fee, 6_000_000);
|
||||
|
||||
Ok(())
|
||||
|
@ -279,16 +287,16 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
// the stored transaction instead
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let slate_i = sender_api.initiate_tx(
|
||||
None,
|
||||
amount * 2, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: amount * 2,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = sender_api.initiate_tx(args)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate)?;
|
||||
slate = sender_api.finalize_tx(&slate)?;
|
||||
|
@ -378,14 +386,17 @@ fn tx_rollback(test_dir: &str) -> Result<(), libwallet::Error> {
|
|||
let mut slate = Slate::blank(1);
|
||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let slate_i = sender_api.initiate_tx(
|
||||
None, amount, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None, None,
|
||||
)?;
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: amount,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let slate_i = sender_api.initiate_tx(args)?;
|
||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||
sender_api.tx_lock_outputs(&slate)?;
|
||||
slate = sender_api.finalize_tx(&slate)?;
|
||||
|
|
|
@ -23,7 +23,7 @@ use crate::keychain;
|
|||
use crate::libwallet;
|
||||
use crate::libwallet::api_impl::{foreign, owner};
|
||||
use crate::libwallet::types::{
|
||||
BlockFees, CbData, NodeClient, WalletBackend, WalletInfo, WalletInst,
|
||||
BlockFees, CbData, InitTxArgs, NodeClient, WalletBackend, WalletInfo, WalletInst,
|
||||
};
|
||||
use crate::lmdb_wallet::LMDBBackend;
|
||||
use crate::util;
|
||||
|
@ -196,15 +196,16 @@ where
|
|||
let slate = {
|
||||
let mut w = wallet.lock();
|
||||
w.open_with_credentials()?;
|
||||
let slate_i = owner::initiate_tx(
|
||||
&mut *w, None, // account
|
||||
amount, // amount
|
||||
2, // minimum confirmations
|
||||
500, // max outputs
|
||||
1, // num change outputs
|
||||
true, // select all outputs
|
||||
None, None, test_mode,
|
||||
)?;
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount,
|
||||
minimum_confirmations: 2,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
..Default::default()
|
||||
};
|
||||
let slate_i = owner::initiate_tx(&mut *w, args, test_mode)?;
|
||||
let slate = client.send_tx_slate_direct(dest, &slate_i)?;
|
||||
owner::tx_lock_outputs(&mut *w, &slate)?;
|
||||
let slate = owner::finalize_tx(&mut *w, &slate)?;
|
||||
|
|
|
@ -25,8 +25,8 @@ use crate::grin_keychain::{Identifier, Keychain};
|
|||
use crate::internal::{keys, selection, tx, updater};
|
||||
use crate::slate::Slate;
|
||||
use crate::types::{
|
||||
AcctPathMapping, NodeClient, OutputCommitMapping, TxEstimation, TxLogEntry, TxWrapper,
|
||||
WalletBackend, WalletInfo,
|
||||
AcctPathMapping, InitTxArgs, NodeClient, NodeHeightResult, OutputCommitMapping, TxLogEntry,
|
||||
TxWrapper, WalletBackend, WalletInfo,
|
||||
};
|
||||
use crate::{Error, ErrorKind};
|
||||
|
||||
|
@ -137,14 +137,7 @@ where
|
|||
/// Initiate tx as sender
|
||||
pub fn initiate_tx<T: ?Sized, C, K>(
|
||||
w: &mut T,
|
||||
src_acct_name: Option<&str>,
|
||||
amount: u64,
|
||||
minimum_confirmations: u64,
|
||||
max_outputs: usize,
|
||||
num_change_outputs: usize,
|
||||
selection_strategy_is_use_all: bool,
|
||||
message: Option<String>,
|
||||
target_slate_version: Option<u16>,
|
||||
args: InitTxArgs,
|
||||
use_test_rng: bool,
|
||||
) -> Result<Slate, Error>
|
||||
where
|
||||
|
@ -152,9 +145,9 @@ where
|
|||
C: NodeClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let parent_key_id = match src_acct_name {
|
||||
let parent_key_id = match args.src_acct_name {
|
||||
Some(d) => {
|
||||
let pm = w.get_acct_path(d.to_owned())?;
|
||||
let pm = w.get_acct_path(d)?;
|
||||
match pm {
|
||||
Some(p) => p.path,
|
||||
None => w.parent_key_id(),
|
||||
|
@ -163,7 +156,7 @@ where
|
|||
None => w.parent_key_id(),
|
||||
};
|
||||
|
||||
let message = match message {
|
||||
let message = match args.message {
|
||||
Some(mut m) => {
|
||||
m.truncate(USER_MESSAGE_MAX_LEN);
|
||||
Some(m)
|
||||
|
@ -171,15 +164,32 @@ where
|
|||
None => None,
|
||||
};
|
||||
|
||||
let mut slate = tx::new_tx_slate(&mut *w, amount, 2, use_test_rng)?;
|
||||
let mut slate = tx::new_tx_slate(&mut *w, args.amount, 2, use_test_rng)?;
|
||||
|
||||
// if we just want to estimate, don't save a context, just send the results
|
||||
// back
|
||||
if let Some(true) = args.estimate_only {
|
||||
let (total, fee) = tx::estimate_send_tx(
|
||||
&mut *w,
|
||||
args.amount,
|
||||
args.minimum_confirmations,
|
||||
args.max_outputs as usize,
|
||||
args.num_change_outputs as usize,
|
||||
args.selection_strategy_is_use_all,
|
||||
&parent_key_id,
|
||||
)?;
|
||||
slate.amount = total;
|
||||
slate.fee = fee;
|
||||
return Ok(slate);
|
||||
}
|
||||
|
||||
let context = tx::add_inputs_to_slate(
|
||||
&mut *w,
|
||||
&mut slate,
|
||||
minimum_confirmations,
|
||||
max_outputs,
|
||||
num_change_outputs,
|
||||
selection_strategy_is_use_all,
|
||||
args.minimum_confirmations,
|
||||
args.max_outputs as usize,
|
||||
args.num_change_outputs as usize,
|
||||
args.selection_strategy_is_use_all,
|
||||
&parent_key_id,
|
||||
0,
|
||||
message,
|
||||
|
@ -193,49 +203,12 @@ where
|
|||
batch.save_private_context(slate.id.as_bytes(), &context)?;
|
||||
batch.commit()?;
|
||||
}
|
||||
if let Some(v) = target_slate_version {
|
||||
if let Some(v) = args.target_slate_version {
|
||||
slate.version_info.orig_version = v;
|
||||
}
|
||||
Ok(slate)
|
||||
}
|
||||
|
||||
/// Estimate
|
||||
pub fn estimate_initiate_tx<T: ?Sized, C, K>(
|
||||
w: &mut T,
|
||||
src_acct_name: Option<&str>,
|
||||
amount: u64,
|
||||
minimum_confirmations: u64,
|
||||
max_outputs: usize,
|
||||
num_change_outputs: usize,
|
||||
selection_strategy_is_use_all: bool,
|
||||
) -> Result<TxEstimation, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: NodeClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let parent_key_id = match src_acct_name {
|
||||
Some(d) => {
|
||||
let pm = w.get_acct_path(d.to_owned())?;
|
||||
match pm {
|
||||
Some(p) => p.path,
|
||||
None => w.parent_key_id(),
|
||||
}
|
||||
}
|
||||
None => w.parent_key_id(),
|
||||
};
|
||||
let (total, fee) = tx::estimate_send_tx(
|
||||
&mut *w,
|
||||
amount,
|
||||
minimum_confirmations,
|
||||
max_outputs,
|
||||
num_change_outputs,
|
||||
selection_strategy_is_use_all,
|
||||
&parent_key_id,
|
||||
)?;
|
||||
Ok(TxEstimation { total, fee })
|
||||
}
|
||||
|
||||
/// Lock sender outputs
|
||||
pub fn tx_lock_outputs<T: ?Sized, C, K>(w: &mut T, slate: &Slate) -> Result<(), Error>
|
||||
where
|
||||
|
@ -348,7 +321,7 @@ where
|
|||
}
|
||||
|
||||
/// node height
|
||||
pub fn node_height<T: ?Sized, C, K>(w: &mut T) -> Result<(u64, bool), Error>
|
||||
pub fn node_height<T: ?Sized, C, K>(w: &mut T) -> Result<NodeHeightResult, Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: NodeClient,
|
||||
|
@ -356,14 +329,20 @@ where
|
|||
{
|
||||
let res = w.w2n_client().get_chain_height();
|
||||
match res {
|
||||
Ok(height) => Ok((height, true)),
|
||||
Ok(height) => Ok(NodeHeightResult {
|
||||
height,
|
||||
updated_from_node: true,
|
||||
}),
|
||||
Err(_) => {
|
||||
let outputs = retrieve_outputs(w, true, false, None)?;
|
||||
let height = match outputs.1.iter().map(|m| m.output.height).max() {
|
||||
Some(height) => height,
|
||||
None => 0,
|
||||
};
|
||||
Ok((height, false))
|
||||
Ok(NodeHeightResult {
|
||||
height,
|
||||
updated_from_node: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -373,29 +373,6 @@ impl fmt::Display for OutputStatus {
|
|||
}
|
||||
}
|
||||
|
||||
/// Map Outputdata to commits
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct OutputCommitMapping {
|
||||
/// Output Data
|
||||
pub output: OutputData,
|
||||
/// The commit
|
||||
#[serde(
|
||||
serialize_with = "secp_ser::as_hex",
|
||||
deserialize_with = "secp_ser::commitment_from_hex"
|
||||
)]
|
||||
pub commit: pedersen::Commitment,
|
||||
}
|
||||
|
||||
/// Transaction Estimate
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct TxEstimation {
|
||||
/// Total amount to be locked
|
||||
#[serde(with = "secp_ser::string_or_u64")]
|
||||
pub total: u64,
|
||||
/// Transaction Fee
|
||||
#[serde(with = "secp_ser::string_or_u64")]
|
||||
pub fee: u64,
|
||||
}
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
/// Holds the context for a single aggsig transaction
|
||||
pub struct Context {
|
||||
|
@ -545,37 +522,6 @@ impl<'de> serde::de::Visitor<'de> for BlockIdentifierVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
/// Fees in block to use for coinbase amount calculation
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct BlockFees {
|
||||
/// fees
|
||||
#[serde(with = "secp_ser::string_or_u64")]
|
||||
pub fees: u64,
|
||||
/// height
|
||||
#[serde(with = "secp_ser::string_or_u64")]
|
||||
pub height: u64,
|
||||
/// key id
|
||||
pub key_id: Option<Identifier>,
|
||||
}
|
||||
|
||||
impl BlockFees {
|
||||
/// return key id
|
||||
pub fn key_id(&self) -> Option<Identifier> {
|
||||
self.key_id.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Response to build a coinbase output.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct CbData {
|
||||
/// Output
|
||||
pub output: Output,
|
||||
/// Kernel
|
||||
pub kernel: TxKernel,
|
||||
/// Key Id
|
||||
pub key_id: Option<Identifier>,
|
||||
}
|
||||
|
||||
/// a contained wallet info struct, so automated tests can parse wallet info
|
||||
/// can add more fields here over time as needed
|
||||
#[derive(Serialize, Eq, PartialEq, Deserialize, Debug, Clone)]
|
||||
|
@ -752,7 +698,11 @@ pub struct TxWrapper {
|
|||
pub tx_hex: String,
|
||||
}
|
||||
|
||||
// Types to facilitate API arguments and serialization
|
||||
|
||||
/// Send TX API Args
|
||||
// TODO: This is here to ensure the legacy V1 API remains intact
|
||||
// remove this when v1 api is removed
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct SendTXArgs {
|
||||
/// amount to send
|
||||
|
@ -774,3 +724,141 @@ pub struct SendTXArgs {
|
|||
/// Optional slate version to target when sending
|
||||
pub target_slate_version: Option<u16>,
|
||||
}
|
||||
|
||||
/// V2 Init / Send TX API Args
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct InitTxArgs {
|
||||
/// The human readable account name from which to draw outputs
|
||||
/// for the transaction, overriding whatever the active account is as set via the
|
||||
/// [`set_active_account`](../grin_wallet_api/owner/struct.Owner.html#method.set_active_account) method.
|
||||
pub src_acct_name: Option<String>,
|
||||
#[serde(with = "secp_ser::string_or_u64")]
|
||||
/// The amount to send, in nanogrins. (`1 G = 1_000_000_000nG`)
|
||||
pub amount: u64,
|
||||
#[serde(with = "secp_ser::string_or_u64")]
|
||||
/// The minimum number of confirmations an output
|
||||
/// should have in order to be included in the transaction.
|
||||
pub minimum_confirmations: u64,
|
||||
/// By default, the wallet selects as many inputs as possible in a
|
||||
/// transaction, to reduce the Output set and the fees. The wallet will attempt to spend
|
||||
/// include up to `max_outputs` in a transaction, however if this is not enough to cover
|
||||
/// the whole amount, the wallet will include more outputs. This parameter should be considered
|
||||
/// a soft limit.
|
||||
pub max_outputs: u32,
|
||||
/// The target number of change outputs to create in the transaction.
|
||||
/// The actual number created will be `num_change_outputs` + whatever remainder is needed.
|
||||
pub num_change_outputs: u32,
|
||||
/// If `true`, attempt to use up as many outputs as
|
||||
/// possible to create the transaction, up the 'soft limit' of `max_outputs`. This helps
|
||||
/// to reduce the size of the UTXO set and the amount of data stored in the wallet, and
|
||||
/// minimizes fees. This will generally result in many inputs and a large change output(s),
|
||||
/// usually much larger than the amount being sent. If `false`, the transaction will include
|
||||
/// as many outputs as are needed to meet the amount, (and no more) starting with the smallest
|
||||
/// value outputs.
|
||||
pub selection_strategy_is_use_all: bool,
|
||||
/// An optional participant message to include alongside the sender's public
|
||||
/// ParticipantData within the slate. This message will include a signature created with the
|
||||
/// sender's private excess value, and will be publically verifiable. Note this message is for
|
||||
/// the convenience of the participants during the exchange; it is not included in the final
|
||||
/// transaction sent to the chain. The message will be truncated to 256 characters.
|
||||
pub message: Option<String>,
|
||||
/// Optionally set the output target slate version (acceptable
|
||||
/// down to the minimum slate version compatible with the current. If `None` the slate
|
||||
/// is generated with the latest version.
|
||||
pub target_slate_version: Option<u16>,
|
||||
/// If true, just return an estimate of the resulting slate, containing fees and amounts
|
||||
/// locked without actually locking outputs or creating the transaction. Note if this is set to
|
||||
/// 'true', the amount field in the slate will contain the total amount locked, not the provided
|
||||
/// transaction amount
|
||||
pub estimate_only: Option<bool>,
|
||||
/// Sender arguments. If present, the underlying function will also attempt to send the
|
||||
/// transaction to a destination and optionally finalize the result
|
||||
pub send_args: Option<InitTxSendArgs>,
|
||||
}
|
||||
|
||||
/// Send TX API Args, for convenience functionality that inits the transaction and sends
|
||||
/// in one go
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct InitTxSendArgs {
|
||||
/// The transaction method. Can currently be 'http' or 'keybase'.
|
||||
pub method: String,
|
||||
/// The destination, contents will depend on the particular method
|
||||
pub dest: String,
|
||||
/// Whether to finalize the result immediately if the send was successful
|
||||
pub finalize: bool,
|
||||
/// Whether to post the transasction if the send and finalize were successful
|
||||
pub post_tx: bool,
|
||||
/// Whether to use dandelion when posting. If false, skip the dandelion relay
|
||||
pub fluff: bool,
|
||||
}
|
||||
|
||||
impl Default for InitTxArgs {
|
||||
fn default() -> InitTxArgs {
|
||||
InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: 0,
|
||||
minimum_confirmations: 10,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: true,
|
||||
message: None,
|
||||
target_slate_version: None,
|
||||
estimate_only: Some(false),
|
||||
send_args: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fees in block to use for coinbase amount calculation
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct BlockFees {
|
||||
/// fees
|
||||
#[serde(with = "secp_ser::string_or_u64")]
|
||||
pub fees: u64,
|
||||
/// height
|
||||
#[serde(with = "secp_ser::string_or_u64")]
|
||||
pub height: u64,
|
||||
/// key id
|
||||
pub key_id: Option<Identifier>,
|
||||
}
|
||||
|
||||
impl BlockFees {
|
||||
/// return key id
|
||||
pub fn key_id(&self) -> Option<Identifier> {
|
||||
self.key_id.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Response to build a coinbase output.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct CbData {
|
||||
/// Output
|
||||
pub output: Output,
|
||||
/// Kernel
|
||||
pub kernel: TxKernel,
|
||||
/// Key Id
|
||||
pub key_id: Option<Identifier>,
|
||||
}
|
||||
|
||||
/// Map Outputdata to commits
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct OutputCommitMapping {
|
||||
/// Output Data
|
||||
pub output: OutputData,
|
||||
/// The commit
|
||||
#[serde(
|
||||
serialize_with = "secp_ser::as_hex",
|
||||
deserialize_with = "secp_ser::commitment_from_hex"
|
||||
)]
|
||||
pub commit: pedersen::Commitment,
|
||||
}
|
||||
|
||||
/// Node height result
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct NodeHeightResult {
|
||||
/// Last known height
|
||||
#[serde(with = "secp_ser::string_or_u64")]
|
||||
pub height: u64,
|
||||
/// Whether this height was updated from the node
|
||||
pub updated_from_node: bool,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue