1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
//! Contact Address book

use crate::api::payment::{build_sign_send_multi_payment, RecipientMemo};
use crate::api::sync::get_latest_height;
use crate::coinconfig::CoinConfig;
use crate::contact::{serialize_contacts, Contact};
use crate::db::AccountData;
use zcash_primitives::memo::Memo;

/// Store contact in the database
/// # Arguments
/// * `id`: contact id
/// * `name`: contact name
/// * `address`: contact address
/// * `dirty`: true if the database hasn't been saved to the blockchain yet
pub fn store_contact(id: u32, name: &str, address: &str, dirty: bool) -> anyhow::Result<()> {
    let c = CoinConfig::get_active();
    let contact = Contact {
        id,
        name: name.to_string(),
        address: address.to_string(),
    };
    c.db()?.store_contact(&contact, dirty)?;
    Ok(())
}

/// Save the new/modified contacts to the blockchain
/// # Arguments
/// * `anchor_offset`: minimum confirmations required for note selection
pub async fn commit_unsaved_contacts(anchor_offset: u32) -> anyhow::Result<String> {
    let c = CoinConfig::get_active();
    let contacts = c.db()?.get_unsaved_contacts()?;
    let memos = serialize_contacts(&contacts)?;
    let tx_id = save_contacts_tx(&memos, anchor_offset).await?;
    Ok(tx_id)
}

async fn save_contacts_tx(memos: &[Memo], anchor_offset: u32) -> anyhow::Result<String> {
    let c = CoinConfig::get_active();
    let last_height = get_latest_height().await?;
    let AccountData { address, .. } = c.db()?.get_account_info(c.id_account)?;
    let recipients: Vec<_> = memos
        .iter()
        .map(|m| RecipientMemo {
            address: address.clone(),
            amount: 0,
            memo: m.clone(),
            max_amount_per_note: 0,
        })
        .collect();

    let tx_id = build_sign_send_multi_payment(
        last_height,
        &recipients,
        false,
        anchor_offset,
        Box::new(|_| {}),
    )
    .await?;
    Ok(tx_id)
}