zingolib 0.0.1

Zingo backend library.
Documentation
//! This mod is mostly to take inputs, raw data amd convert it into lightclient actions
//! (obviously) in a test environment.

use zcash_primitives::transaction::TxId;
use zcash_protocol::{PoolType, ShieldedProtocol};

use crate::{
    lightclient::{LightClient, describe::UAReceivers, error::LightClientError},
    wallet::LightWallet,
};

/// Create a lightclient from the buffer of another
pub async fn new_client_from_save_buffer(
    template_client: &mut LightClient,
) -> Result<LightClient, LightClientError> {
    let mut wallet_bytes: Vec<u8> = vec![];
    template_client
        .wallet
        .lock()
        .await
        .write(&mut wallet_bytes, &template_client.config.chain)
        .await?;

    LightClient::create_from_wallet(
        LightWallet::read(wallet_bytes.as_slice(), template_client.config.chain)?,
        template_client.config.clone(),
        false,
    )
}
/// gets the first address that will allow a sender to send to a specific pool, as a string
/// calling \[0] on json may panic? not sure -fv
pub async fn get_base_address(client: &LightClient, pooltype: PoolType) -> String {
    match pooltype {
        PoolType::Transparent => {
            client.do_addresses(UAReceivers::All).await[0]["receivers"]["transparent"]
                .clone()
                .to_string()
        }
        PoolType::Shielded(ShieldedProtocol::Sapling) => {
            client.do_addresses(UAReceivers::All).await[0]["receivers"]["sapling"]
                .clone()
                .to_string()
        }
        PoolType::Shielded(ShieldedProtocol::Orchard) => {
            client.do_addresses(UAReceivers::All).await[0]["address"]
                .take()
                .to_string()
        }
    }
}
/// Get the total fees paid by a given client (assumes 1 capability per client).
pub async fn get_fees_paid_by_client(client: &LightClient) -> u64 {
    client.transaction_summaries().await.unwrap().paid_fees()
}
/// Helpers to provide raw_receivers to lightclients for send and shield, etc.
pub mod from_inputs {

    use nonempty::NonEmpty;
    use zcash_primitives::transaction::TxId;

    use crate::{
        lightclient::{LightClient, error::QuickSendError},
        wallet::error::ProposeSendError,
    };

    /// Panics if the address, amount or memo conversion fails.
    pub async fn quick_send(
        quick_sender: &mut crate::lightclient::LightClient,
        raw_receivers: Vec<(&str, u64, Option<&str>)>,
    ) -> Result<NonEmpty<TxId>, QuickSendError> {
        let request = transaction_request_from_send_inputs(raw_receivers)
            .expect("should be able to create a transaction request as receivers are valid.");
        quick_sender.quick_send(request).await
    }

    /// Panics if the address, amount or memo conversion fails.
    pub(crate) fn receivers_from_send_inputs(
        raw_receivers: Vec<(&str, u64, Option<&str>)>,
    ) -> crate::data::receivers::Receivers {
        raw_receivers
            .into_iter()
            .map(|(address, amount, memo)| {
                let recipient_address = crate::utils::conversion::address_from_str(address)
                    .expect("should be a valid address");
                let amount = crate::utils::conversion::zatoshis_from_u64(amount)
                    .expect("should be inside the range of valid zatoshis");
                let memo = memo.map(|memo| {
                    crate::wallet::utils::interpret_memo_string(memo.to_string())
                        .expect("should be able to interpret memo")
                });

                crate::data::receivers::Receiver::new(recipient_address, amount, memo)
            })
            .collect()
    }

    /// Creates a [`zcash_client_backend::zip321::TransactionRequest`] from rust primitives for simplified test writing.
    pub fn transaction_request_from_send_inputs(
        raw_receivers: Vec<(&str, u64, Option<&str>)>,
    ) -> Result<
        zcash_client_backend::zip321::TransactionRequest,
        zcash_client_backend::zip321::Zip321Error,
    > {
        let receivers = receivers_from_send_inputs(raw_receivers);
        crate::data::receivers::transaction_request_from_receivers(receivers)
    }

    /// Panics if the address, amount or memo conversion fails.
    pub async fn propose(
        proposer: &mut LightClient,
        raw_receivers: Vec<(&str, u64, Option<&str>)>,
    ) -> Result<crate::data::proposal::ProportionalFeeProposal, ProposeSendError> {
        let request = transaction_request_from_send_inputs(raw_receivers)
            .expect("should be able to create a transaction request as receivers are valid.");
        proposer.propose_send(request).await
    }
}

/// gets stati for a vec of txids
pub async fn lookup_statuses(
    client: &LightClient,
    txids: nonempty::NonEmpty<TxId>,
) -> nonempty::NonEmpty<Option<zingo_status::confirmation_status::ConfirmationStatus>> {
    let wallet = client.wallet.lock().await;

    txids.map(|txid| {
        wallet
            .wallet_transactions
            .get(&txid)
            .map(|transaction_record| transaction_record.status())
    })
}