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,
    /* private fields */
}
Expand description

Main interface into all wallet API functions. Wallet APIs are split into two seperate blocks of functionality called the ‘Owner’ and ‘Foreign’ APIs

  • The ‘Foreign’ API contains methods that other wallets will use to interact with the owner’s wallet. This API can be exposed to the outside world, with the consideration as to how that can be done securely up to the implementor.

Methods in both APIs are intended to be ‘single use’, that is to say each method will ‘open’ the wallet (load the keychain with its master seed), perform its operation, then ‘close’ the wallet (unloading references to the keychain and master seed).

Fields§

§wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>

Wallet instance

§doctest_mode: bool

Flag to normalize some output during testing. Can mostly be ignored.

Implementations§

source§

impl<'a, L, C, K> Foreign<'a, L, C, K>where L: WalletLCProvider<'a, C, K>, C: NodeClient + 'a, K: Keychain + 'a,

source

pub fn new( wallet_inst: Arc<Mutex<Box<dyn WalletInst<'a, L, C, K>>>>, keychain_mask: Option<SecretKey>, middleware: Option<ForeignCheckMiddleware> ) -> Self

Create a new API instance with the given wallet instance. All subsequent API calls will operate on this instance of the wallet.

Each method will call the WalletBackend’s open_with_credentials (initialising a keychain with the master seed), perform its operation, then close the keychain with a call to close

Arguments
  • wallet_in - A reference-counted mutex containing an implementation of the WalletBackend trait.
  • keychain_mask - Mask value stored internally to use when calling a wallet whose seed has been XORed with a token value (such as when running the foreign and owner listeners in the same instance)
  • middleware - Option middleware which containts the NodeVersionInfo and can call a predefined function with the slate to check if the operation should continue
Returns
  • An instance of the ForeignApi holding a reference to the provided wallet
Example
use epic_wallet_util::epic_keychain as keychain;
use epic_wallet_util::epic_util as util;
use epic_wallet_api as api;
use stack_epic_wallet_config as config;
use stack_epic_wallet_impls as impls;
use stack_epic_wallet_libwallet as libwallet;

use keychain::ExtKeychain;
use tempfile::tempdir;

use std::sync::Arc;
use util::{Mutex, ZeroingString};

use api::Foreign;
use config::WalletConfig;
use impls::{DefaultWalletImpl, DefaultLCProvider, HTTPNodeClient};
use libwallet::WalletInst;

let mut wallet_config = WalletConfig::default();

// A NodeClient must first be created to handle communication between
// the wallet and the node.
let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);

// impls::DefaultWalletImpl is provided for convenience in instantiating the wallet
// It contains the LMDBBackend, DefaultLCProvider (lifecycle) and ExtKeychain used
// by the reference wallet implementation.
// These traits can be replaced with alternative implementations if desired

let mut wallet = Box::new(DefaultWalletImpl::<'static, HTTPNodeClient>::new(node_client.clone()).unwrap())
	as Box<WalletInst<'static, DefaultLCProvider<HTTPNodeClient, ExtKeychain>, HTTPNodeClient, ExtKeychain>>;

// Wallet LifeCycle Provider provides all functions init wallet and work with seeds, etc...
let lc = wallet.lc_provider().unwrap();

// The top level wallet directory should be set manually (in the reference implementation,
// this is provided in the WalletConfig)
let _ = lc.set_top_level_directory(&wallet_config.data_file_dir);

// Wallet must be opened with the password (TBD)
let pw = ZeroingString::from("wallet_password");
lc.open_wallet(None, pw, false, false);

// All wallet functions operate on an Arc::Mutex to allow multithreading where needed
let mut wallet = Arc::new(Mutex::new(wallet));

let api_foreign = Foreign::new(wallet.clone(), None, None);
// .. perform wallet operations
source

pub fn check_version(&self) -> Result<VersionInfo, Error>

Return the version capabilities of the running ForeignApi Node

Arguments

None

Returns
Example

Set up as in new method above.


let mut api_foreign = Foreign::new(wallet.clone(), None, None);

let version_info = api_foreign.check_version();
// check and proceed accordingly
source

pub fn build_coinbase(&self, block_fees: &BlockFees) -> Result<CbData, Error>

Builds a new unconfirmed coinbase output in the wallet, generally for inclusion in a potential new block’s coinbase output during mining.

All potential coinbase outputs are created as ‘Unconfirmed’ with the coinbase flag set. If a potential coinbase output is found on the chain after a wallet update, it status is set to Unsent and a Transaction Log Entry will be created. Note the output will be unspendable until the coinbase maturity period has expired.

Arguments
  • block_fees - A BlockFees struct, set up as follows:

fees - should contain the sum of all transaction fees included in the potential block

height - should contain the block height being mined

key_id - can optionally contain the corresponding keychain ID in the wallet to use to create the output’s blinding factor. If this is not provided, the next available key id will be assigned

Returns
  • Ok(cb_data) if successful. This will contain the corresponding output, kernel and keyID used to create the coinbase output.
  • or libwallet::Error if an error is encountered.
Example

Set up as in new method above.


let mut api_foreign = Foreign::new(wallet.clone(), None, None);

let block_fees = BlockFees {
	fees: 800000,
	height: 234323,
	key_id: None,
};
// Build a new coinbase output

let res = api_foreign.build_coinbase(&block_fees);

if let Ok(cb_data) = res {
	// cb_data is populated with coinbase output info
	// ...
}
source

pub fn build_foundation(&self, block_fees: &BlockFees) -> Result<CbData, Error>

Builds a new foundation for the wallet

source

pub fn verify_slate_messages(&self, slate: &Slate) -> Result<(), Error>

Verifies all messages in the slate match their public keys.

The option messages themselves are part of the participant_data field within the slate. Messages are signed with the same key used to sign for the paricipant’s inputs, and can thus be verified with the public key found in the public_blind_excess field. This function is a simple helper to returns whether all signatures in the participant data match their public keys.

Arguments
  • slate - The transaction Slate.
Returns
  • Ok(()) if successful and the signatures validate
  • or libwallet::Error if an error is encountered.
Example

Set up as in new method above.


let mut api_foreign = Foreign::new(wallet.clone(), None, None);

// Receive a slate via some means

let res = api_foreign.verify_slate_messages(&slate);

if let Err(e) = res {
	// Messages don't validate, likely return an error
	// ...
} else {
	// Slate messages are fine
}

source

pub fn receive_tx( &self, slate: &Slate, dest_acct_name: Option<&str>, message: Option<String> ) -> Result<Slate, Error>

Recieve a tranaction created by another party, returning the modified Slate object, modified with the recipient’s output for the transaction amount, and public signature data. This slate can then be sent back to the sender to finalize the transaction via the Owner API’s finalize_tx method.

This function creates a single output for the full amount, set to a status of ‘Awaiting finalization’. It will remain in this state until the wallet finds the corresponding output on the chain, at which point it will become ‘Unspent’. The slate will be updated with the results of Signing round 1 and 2, adding the recipient’s public nonce, public excess value, and partial signature to the slate.

Also creates a corresponding Transaction Log Entry in the wallet’s transaction log.

Arguments
  • slate - The transaction Slate. The slate should contain the results of the sender’s round 1 (e.g, public nonce and public excess value).
  • dest_acct_name - The name of the account into which the slate should be received. If None, the default account is used.
  • message - An optional participant message to include alongside the recipient’s public ParticipantData within the slate. This message will include a signature created with the recipient’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.
Returns
  • a result containing:
  • Ok(slate) if successful, containing the new slate updated with the recipient’s output and public signing information.
  • or libwallet::Error if an error is encountered.
Remarks
  • This method will store a partially completed transaction in the wallet’s transaction log.
Example

Set up as in new method above.


let mut api_foreign = Foreign::new(wallet.clone(), None, None);

// . . .
// Obtain a sent slate somehow
let result = api_foreign.receive_tx(&slate, None, None);

if let Ok(slate) = result {
	// Send back to recipient somehow
	// ...
}
source

pub fn finalize_invoice_tx(&self, slate: &Slate) -> Result<Slate, Error>

Finalizes an invoice transaction initiated by this wallet’s Owner api. This step assumes the paying party has completed round 1 and 2 of slate creation, and added their partial signatures. The invoicer will verify and add their partial sig, then create the finalized transaction, ready to post to a node.

Note that this function DOES NOT POST the transaction to a node for validation. This is done in separately via the post_tx function.

This function also stores the final transaction in the user’s wallet files for retrieval via the get_stored_tx function.

Arguments
  • slate - The transaction Slate. The payer should have filled in round 1 and 2.
Returns
  • Ok(slate) if successful, containing the new finalized slate.
  • or libwallet::Error if an error is encountered.
Example

Set up as in new method above.


let mut api_owner = Owner::new(wallet.clone());
let mut api_foreign = Foreign::new(wallet.clone(), None, None);

// . . .
// Issue the invoice tx via the owner API
let args = IssueInvoiceTxArgs {
	amount: 10_000_000_000,
	..Default::default()
};
let result = api_owner.issue_invoice_tx(None, args);

// If result okay, send to payer, who will apply the transaction via their
// owner API, then send back the slate
// ...

let slate = api_foreign.finalize_invoice_tx(&slate);
// if okay, then post via the owner API

Trait Implementations§

source§

impl<'a, L, C, K> ForeignRpc for Foreign<'a, L, C, K>where L: WalletLCProvider<'a, C, K>, C: NodeClient + 'a, K: Keychain + 'a,

source§

fn check_version(&self) -> Result<VersionInfo, ErrorKind>

Networked version of Foreign::check_version. Read more
source§

fn build_coinbase( &self, block_fees: &BlockFees ) -> Result<VersionedCoinbase, ErrorKind>

Networked Legacy (non-secure token) version of Foreign::build_coinbase. Read more
source§

fn build_foundation( &self, block_fees: &BlockFees ) -> Result<VersionedCoinbase, ErrorKind>

Build a coinbase transaction
source§

fn verify_slate_messages(&self, slate: VersionedSlate) -> Result<(), ErrorKind>

source§

fn receive_tx( &self, in_slate: VersionedSlate, dest_acct_name: Option<String>, message: Option<String> ) -> Result<VersionedSlate, ErrorKind>

Networked version of Foreign::receive_tx. Read more
source§

fn finalize_invoice_tx( &self, in_slate: VersionedSlate ) -> Result<VersionedSlate, ErrorKind>

Auto Trait Implementations§

§

impl<'a, L, C, K> !RefUnwindSafe for Foreign<'a, L, C, K>

§

impl<'a, L, C, K> Send for Foreign<'a, L, C, K>

§

impl<'a, L, C, K> Sync for Foreign<'a, L, C, K>

§

impl<'a, L, C, K> Unpin for Foreign<'a, L, C, K>

§

impl<'a, L, C, K> !UnwindSafe for Foreign<'a, L, C, K>

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Conv for T

§

fn conv<T>(self) -> Twhere Self: Into<T>,

Converts self into T using Into<T>. Read more
§

impl<T> FmtForward for T

§

fn fmt_binary(self) -> FmtBinary<Self>where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
§

fn fmt_display(self) -> FmtDisplay<Self>where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
§

fn fmt_octal(self) -> FmtOctal<Self>where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
§

fn fmt_pointer(self) -> FmtPointer<Self>where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
§

fn fmt_list(self) -> FmtList<Self>where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> Pipe for Twhere T: ?Sized,

§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> Rwhere Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R ) -> Rwhere Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> Rwhere Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> Rwhere Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> Rwhere Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R ) -> Rwhere Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
§

impl<T> Pointable for T

§

const ALIGN: usize = mem::align_of::<T>()

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> SafeBorrow<T> for Twhere T: ?Sized,

§

fn borrow_replacement(ptr: &T) -> &T

Given ptr, which was obtained from a prior call to Self::borrow(), return a value with the same nominal lifetime which is guaranteed to survive mutations to Self. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
§

impl<T> Tap for T

§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Selfwhere Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Selfwhere Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Selfwhere Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Selfwhere Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Selfwhere Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Selfwhere Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Selfwhere Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Selfwhere Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
§

impl<T> TryConv for T

§

fn try_conv<T>(self) -> Result<T, Self::Error>where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for Twhere V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> Erased for T

§

impl<T> UnsafeAny for Twhere T: Any,