use crate::keychain::Keychain;
use crate::libwallet::api_impl::foreign;
use crate::libwallet::{
BlockFees, CbData, Error, NodeClient, NodeVersionInfo, Slate, VersionInfo, WalletInst,
WalletLCProvider,
};
use crate::util::secp::key::SecretKey;
use crate::util::Mutex;
use std::sync::Arc;
pub type ForeignCheckMiddleware =
fn(ForeignCheckMiddlewareFn, Option<NodeVersionInfo>, Option<&Slate>) -> Result<(), Error>;
pub enum ForeignCheckMiddlewareFn {
CheckVersion,
BuildCoinbase,
VerifySlateMessages,
ReceiveTx,
FinalizeInvoiceTx,
}
pub struct Foreign<'a, L, C, K>
where
L: WalletLCProvider<'a, C, K>,
C: NodeClient + 'a,
K: Keychain + 'a,
{
pub wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
pub doctest_mode: bool,
middleware: Option<ForeignCheckMiddleware>,
keychain_mask: Option<SecretKey>,
}
impl<'a, L, C, K> Foreign<'a, L, C, K>
where
L: WalletLCProvider<'a, C, K>,
C: NodeClient + 'a,
K: Keychain + 'a,
{
pub fn new(
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>,
keychain_mask: Option<SecretKey>,
middleware: Option<ForeignCheckMiddleware>,
) -> Self {
Foreign {
wallet_inst,
doctest_mode: false,
middleware,
keychain_mask,
}
}
pub fn check_version(&self) -> Result<VersionInfo, Error> {
if let Some(m) = self.middleware.as_ref() {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
m(
ForeignCheckMiddlewareFn::CheckVersion,
w.w2n_client().get_version_info(),
None,
)?;
}
Ok(foreign::check_version())
}
pub fn build_coinbase(&self, block_fees: &BlockFees) -> Result<CbData, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
if let Some(m) = self.middleware.as_ref() {
m(
ForeignCheckMiddlewareFn::BuildCoinbase,
w.w2n_client().get_version_info(),
None,
)?;
}
foreign::build_coinbase(
&mut **w,
(&self.keychain_mask).as_ref(),
block_fees,
self.doctest_mode,
)
}
pub fn build_foundation(&self, block_fees: &BlockFees) -> Result<CbData, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
if let Some(m) = self.middleware.as_ref() {
m(
ForeignCheckMiddlewareFn::BuildCoinbase,
w.w2n_client().get_version_info(),
None,
)?;
}
foreign::build_foundation(
&mut **w,
(&self.keychain_mask).as_ref(),
block_fees,
self.doctest_mode,
)
}
pub fn verify_slate_messages(&self, slate: &Slate) -> Result<(), Error> {
if let Some(m) = self.middleware.as_ref() {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
m(
ForeignCheckMiddlewareFn::VerifySlateMessages,
w.w2n_client().get_version_info(),
Some(slate),
)?;
}
foreign::verify_slate_messages(slate)
}
pub fn receive_tx(
&self,
slate: &Slate,
dest_acct_name: Option<&str>,
message: Option<String>,
) -> Result<Slate, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
if let Some(m) = self.middleware.as_ref() {
m(
ForeignCheckMiddlewareFn::ReceiveTx,
w.w2n_client().get_version_info(),
Some(slate),
)?;
}
foreign::receive_tx(
&mut **w,
(&self.keychain_mask).as_ref(),
slate,
dest_acct_name,
message,
None,
self.doctest_mode,
)
}
pub fn finalize_invoice_tx(&self, slate: &Slate) -> Result<Slate, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
if let Some(m) = self.middleware.as_ref() {
m(
ForeignCheckMiddlewareFn::FinalizeInvoiceTx,
w.w2n_client().get_version_info(),
Some(slate),
)?;
}
foreign::finalize_invoice_tx(&mut **w, (&self.keychain_mask).as_ref(), slate)
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! doctest_helper_setup_doc_env_foreign {
($wallet:ident, $wallet_config:ident) => {
use epic_wallet_api as api;
use epic_wallet_config as config;
use epic_wallet_impls as impls;
use epic_wallet_libwallet as libwallet;
use epic_wallet_util::epic_keychain as keychain;
use epic_wallet_util::epic_util as util;
use keychain::ExtKeychain;
use tempfile::tempdir;
use std::sync::Arc;
use util::{Mutex, ZeroingString};
use api::{Foreign, Owner};
use config::WalletConfig;
use impls::{DefaultLCProvider, DefaultWalletImpl, HTTPNodeClient};
use libwallet::{BlockFees, IssueInvoiceTxArgs, Slate, WalletInst};
let dir = tempdir().map_err(|e| format!("{:#?}", e)).unwrap();
let dir = dir
.path()
.to_str()
.ok_or("Failed to convert tmpdir path to string.".to_owned())
.unwrap();
let mut wallet_config = WalletConfig::default();
wallet_config.data_file_dir = dir.to_owned();
let pw = ZeroingString::from("");
let node_client =
HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None).unwrap();
let mut wallet = Box::new(
DefaultWalletImpl::<'static, HTTPNodeClient>::new(node_client.clone()).unwrap(),
)
as Box<
WalletInst<
'static,
DefaultLCProvider<HTTPNodeClient, ExtKeychain>,
HTTPNodeClient,
ExtKeychain,
>,
>;
let lc = wallet.lc_provider().unwrap();
let _ = lc.set_top_level_directory(&wallet_config.data_file_dir);
lc.open_wallet(None, pw, false, false);
let mut $wallet = Arc::new(Mutex::new(wallet));
};
}