API: get_available_addrs
This commit is contained in:
parent
dbaa1c02c9
commit
8a2f2b7fea
|
@ -226,6 +226,8 @@ struct CResult_u8 convert_to_watchonly(uint8_t coin, uint32_t id_account);
|
||||||
|
|
||||||
struct CResult______u8 get_backup(uint8_t coin, uint32_t id_account);
|
struct CResult______u8 get_backup(uint8_t coin, uint32_t id_account);
|
||||||
|
|
||||||
|
struct CResult_u8 get_available_addrs(uint8_t coin, uint32_t account);
|
||||||
|
|
||||||
struct CResult_____c_char get_address(uint8_t coin, uint32_t id_account, uint8_t ua_type);
|
struct CResult_____c_char get_address(uint8_t coin, uint32_t id_account, uint8_t ua_type);
|
||||||
|
|
||||||
void import_transparent_key(uint8_t coin, uint32_t id_account, char *path);
|
void import_transparent_key(uint8_t coin, uint32_t id_account, char *path);
|
||||||
|
|
|
@ -3,9 +3,7 @@
|
||||||
// Account creation
|
// Account creation
|
||||||
|
|
||||||
use crate::coinconfig::CoinConfig;
|
use crate::coinconfig::CoinConfig;
|
||||||
use crate::db::data_generated::fb::{
|
use crate::db::data_generated::fb::{AddressBalanceT, AddressBalanceVecT, BackupT, KeyPackT};
|
||||||
BackupT, KeyPackT, AddressBalanceVecT, AddressBalanceT,
|
|
||||||
};
|
|
||||||
use crate::db::AccountData;
|
use crate::db::AccountData;
|
||||||
use crate::key2::decode_key;
|
use crate::key2::decode_key;
|
||||||
use crate::orchard::OrchardKeyBytes;
|
use crate::orchard::OrchardKeyBytes;
|
||||||
|
@ -265,22 +263,39 @@ pub async fn get_taddr_balance(coin: u8, id_account: u32) -> anyhow::Result<u64>
|
||||||
/// is exceeded and no balance was found
|
/// is exceeded and no balance was found
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `gap_limit`: number of accounts with 0 balance before the scan stops
|
/// * `gap_limit`: number of accounts with 0 balance before the scan stops
|
||||||
pub async fn scan_transparent_accounts(coin: u8, account: u32, gap_limit: usize) -> anyhow::Result<AddressBalanceVecT> {
|
pub async fn scan_transparent_accounts(
|
||||||
|
coin: u8,
|
||||||
|
account: u32,
|
||||||
|
gap_limit: usize,
|
||||||
|
) -> anyhow::Result<AddressBalanceVecT> {
|
||||||
let c = CoinConfig::get(coin);
|
let c = CoinConfig::get(coin);
|
||||||
let db = c.db()?;
|
let db = c.db()?;
|
||||||
let account_data = db.get_account_info(account)?;
|
let account_data = db.get_account_info(account)?;
|
||||||
let AccountData {
|
let AccountData { seed, aindex, .. } = account_data;
|
||||||
seed, aindex, ..
|
|
||||||
} = account_data;
|
|
||||||
let mut addresses = vec![];
|
let mut addresses = vec![];
|
||||||
if let Some(seed) = seed {
|
if let Some(seed) = seed {
|
||||||
let mut client = c.connect_lwd().await?;
|
let mut client = c.connect_lwd().await?;
|
||||||
addresses.extend(crate::taddr::scan_transparent_accounts(c.chain.network(), &mut client, &seed, aindex, gap_limit).await?);
|
addresses.extend(
|
||||||
|
crate::taddr::scan_transparent_accounts(
|
||||||
|
c.chain.network(),
|
||||||
|
&mut client,
|
||||||
|
&seed,
|
||||||
|
aindex,
|
||||||
|
gap_limit,
|
||||||
|
)
|
||||||
|
.await?,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let addresses: Vec<_> = addresses.iter().map(|a| AddressBalanceT { index: a.index,
|
let addresses: Vec<_> = addresses
|
||||||
address: Some(a.address.clone()), balance: a.balance }).collect();
|
.iter()
|
||||||
|
.map(|a| AddressBalanceT {
|
||||||
|
index: a.index,
|
||||||
|
address: Some(a.address.clone()),
|
||||||
|
balance: a.balance,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
let addresses = AddressBalanceVecT {
|
let addresses = AddressBalanceVecT {
|
||||||
values: Some(addresses)
|
values: Some(addresses),
|
||||||
};
|
};
|
||||||
Ok(addresses)
|
Ok(addresses)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,13 @@ static mut POST_COBJ: Option<ffi::DartPostCObjectFnType> = None;
|
||||||
|
|
||||||
const MAX_COINS: u8 = 2;
|
const MAX_COINS: u8 = 2;
|
||||||
|
|
||||||
|
fn with_coin<T, F: Fn(&Connection) -> anyhow::Result<T>>(coin: u8, f: F) -> anyhow::Result<T> {
|
||||||
|
let c = CoinConfig::get(coin);
|
||||||
|
let db = c.db()?;
|
||||||
|
let connection = &db.connection;
|
||||||
|
f(connection)
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn dummy_export() {}
|
pub unsafe extern "C" fn dummy_export() {}
|
||||||
|
|
||||||
|
@ -255,6 +262,15 @@ pub unsafe extern "C" fn get_backup(coin: u8, id_account: u32) -> CResult<*const
|
||||||
to_cresult_bytes(res())
|
to_cresult_bytes(res())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn get_available_addrs(coin: u8, account: u32) -> CResult<u8> {
|
||||||
|
let res = |connection: &Connection| {
|
||||||
|
let res = crate::db::read::get_available_addrs(connection, account)?;
|
||||||
|
Ok(res)
|
||||||
|
};
|
||||||
|
to_cresult(with_coin(coin, res))
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn get_address(
|
pub unsafe extern "C" fn get_address(
|
||||||
coin: u8,
|
coin: u8,
|
||||||
|
@ -507,9 +523,15 @@ pub async unsafe extern "C" fn shield_taddr(
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub async unsafe extern "C" fn scan_transparent_accounts(coin: u8, account: u32, gap_limit: u32) -> CResult<*const u8> {
|
pub async unsafe extern "C" fn scan_transparent_accounts(
|
||||||
|
coin: u8,
|
||||||
|
account: u32,
|
||||||
|
gap_limit: u32,
|
||||||
|
) -> CResult<*const u8> {
|
||||||
let res = async {
|
let res = async {
|
||||||
let addresses = crate::api::account::scan_transparent_accounts(coin, account, gap_limit as usize).await?;
|
let addresses =
|
||||||
|
crate::api::account::scan_transparent_accounts(coin, account, gap_limit as usize)
|
||||||
|
.await?;
|
||||||
let mut builder = FlatBufferBuilder::new();
|
let mut builder = FlatBufferBuilder::new();
|
||||||
let root = addresses.pack(&mut builder);
|
let root = addresses.pack(&mut builder);
|
||||||
builder.finish(root, None);
|
builder.finish(root, None);
|
||||||
|
@ -877,13 +899,6 @@ pub unsafe extern "C" fn clear_tx_details(coin: u8, account: u32) -> CResult<u8>
|
||||||
to_cresult(with_coin(coin, res))
|
to_cresult(with_coin(coin, res))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_coin<T, F: Fn(&Connection) -> anyhow::Result<T>>(coin: u8, f: F) -> anyhow::Result<T> {
|
|
||||||
let c = CoinConfig::get(coin);
|
|
||||||
let db = c.db()?;
|
|
||||||
let connection = &db.connection;
|
|
||||||
f(connection)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn get_account_list(coin: u8) -> CResult<*const u8> {
|
pub unsafe extern "C" fn get_account_list(coin: u8) -> CResult<*const u8> {
|
||||||
let res = |connection: &Connection| {
|
let res = |connection: &Connection| {
|
||||||
|
@ -1142,10 +1157,7 @@ pub unsafe extern "C" fn clone_db_with_passwd(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn get_property(
|
pub unsafe extern "C" fn get_property(coin: u8, name: *mut c_char) -> CResult<*mut c_char> {
|
||||||
coin: u8,
|
|
||||||
name: *mut c_char,
|
|
||||||
) -> CResult<*mut c_char> {
|
|
||||||
from_c_str!(name);
|
from_c_str!(name);
|
||||||
let res = |connection: &Connection| {
|
let res = |connection: &Connection| {
|
||||||
let value = crate::db::read::get_property(connection, &name)?;
|
let value = crate::db::read::get_property(connection, &name)?;
|
||||||
|
|
|
@ -1131,10 +1131,7 @@ impl DbAdapter {
|
||||||
"UPDATE transactions SET address = NULL, memo = NULL WHERE account = ?1",
|
"UPDATE transactions SET address = NULL, memo = NULL WHERE account = ?1",
|
||||||
[account],
|
[account],
|
||||||
)?;
|
)?;
|
||||||
connection.execute(
|
connection.execute("DELETE FROM messages WHERE account = ?1", [account])?;
|
||||||
"DELETE FROM messages WHERE account = ?1",
|
|
||||||
[account],
|
|
||||||
)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -294,7 +294,8 @@ pub fn get_messages(network: &Network, connection: &Connection, id: u32) -> Resu
|
||||||
let mut stmt = connection.prepare(
|
let mut stmt = connection.prepare(
|
||||||
"SELECT m.id, m.id_tx, m.timestamp, m.sender, m.recipient, m.incoming, \
|
"SELECT m.id, m.id_tx, m.timestamp, m.sender, m.recipient, m.incoming, \
|
||||||
subject, body, height, read FROM messages m \
|
subject, body, height, read FROM messages m \
|
||||||
WHERE account = ?1 ORDER BY timestamp DESC")?;
|
WHERE account = ?1 ORDER BY timestamp DESC",
|
||||||
|
)?;
|
||||||
let rows = stmt.query_map(params![id], |row| {
|
let rows = stmt.query_map(params![id], |row| {
|
||||||
let id_msg: u32 = row.get("id")?;
|
let id_msg: u32 = row.get("id")?;
|
||||||
let id_tx: Option<u32> = row.get("id_tx")?;
|
let id_tx: Option<u32> = row.get("id_tx")?;
|
||||||
|
@ -329,7 +330,9 @@ pub fn get_messages(network: &Network, connection: &Connection, id: u32) -> Resu
|
||||||
for r in rows {
|
for r in rows {
|
||||||
messages.push(r?);
|
messages.push(r?);
|
||||||
}
|
}
|
||||||
let messages = MessageVecT { messages: Some(messages) };
|
let messages = MessageVecT {
|
||||||
|
messages: Some(messages),
|
||||||
|
};
|
||||||
Ok(messages)
|
Ok(messages)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,15 +663,48 @@ pub fn resolve_addresses(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_property(connection: &Connection, name: &str) -> anyhow::Result<String> {
|
pub fn get_property(connection: &Connection, name: &str) -> anyhow::Result<String> {
|
||||||
let url = connection.query_row("SELECT value FROM properties WHERE name = ?1", [name], |row| {
|
let url = connection
|
||||||
|
.query_row(
|
||||||
|
"SELECT value FROM properties WHERE name = ?1",
|
||||||
|
[name],
|
||||||
|
|row| {
|
||||||
let url: String = row.get(0)?;
|
let url: String = row.get(0)?;
|
||||||
Ok(url)
|
Ok(url)
|
||||||
}).optional()?;
|
},
|
||||||
|
)
|
||||||
|
.optional()?;
|
||||||
Ok(url.unwrap_or(String::new()))
|
Ok(url.unwrap_or(String::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_property(connection: &Connection, name: &str, value: &str) -> anyhow::Result<()> {
|
pub fn set_property(connection: &Connection, name: &str, value: &str) -> anyhow::Result<()> {
|
||||||
connection.execute("INSERT INTO properties(name, value) VALUES (?1, ?2) ON CONFLICT (name) \
|
connection.execute(
|
||||||
DO UPDATE SET value = excluded.value", params![name, value])?;
|
"INSERT INTO properties(name, value) VALUES (?1, ?2) ON CONFLICT (name) \
|
||||||
|
DO UPDATE SET value = excluded.value",
|
||||||
|
params![name, value],
|
||||||
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_available_addrs(connection: &Connection, account: u32) -> anyhow::Result<u8> {
|
||||||
|
let has_transparent = connection
|
||||||
|
.query_row(
|
||||||
|
"SELECT 1 FROM taddrs WHERE account = ?1",
|
||||||
|
[account],
|
||||||
|
|_row| Ok(()),
|
||||||
|
)
|
||||||
|
.optional()?
|
||||||
|
.is_some();
|
||||||
|
let has_sapling = true;
|
||||||
|
let has_orchard = connection
|
||||||
|
.query_row(
|
||||||
|
"SELECT 1 FROM orchard_addrs WHERE account = ?1",
|
||||||
|
[account],
|
||||||
|
|_row| Ok(()),
|
||||||
|
)
|
||||||
|
.optional()?
|
||||||
|
.is_some();
|
||||||
|
let res = if has_transparent { 1 } else { 0 }
|
||||||
|
| if has_sapling { 2 } else { 0 }
|
||||||
|
| if has_orchard { 4 } else { 0 };
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
25
src/taddr.rs
25
src/taddr.rs
|
@ -1,14 +1,14 @@
|
||||||
use crate::api::payment_v2::build_tx_plan_with_utxos;
|
use crate::api::payment_v2::build_tx_plan_with_utxos;
|
||||||
use crate::api::recipient::RecipientMemo;
|
use crate::api::recipient::RecipientMemo;
|
||||||
use crate::chain::{get_checkpoint_height, EXPIRY_HEIGHT_OFFSET, get_latest_height};
|
use crate::chain::{get_checkpoint_height, get_latest_height, EXPIRY_HEIGHT_OFFSET};
|
||||||
use crate::coinconfig::CoinConfig;
|
use crate::coinconfig::CoinConfig;
|
||||||
use crate::db::AccountData;
|
use crate::db::AccountData;
|
||||||
use crate::key2::split_key;
|
use crate::key2::split_key;
|
||||||
use crate::note_selection::{SecretKeys, Source, UTXO};
|
use crate::note_selection::{SecretKeys, Source, UTXO};
|
||||||
use crate::unified::orchard_as_unified;
|
use crate::unified::orchard_as_unified;
|
||||||
use crate::{
|
use crate::{
|
||||||
broadcast_tx, build_tx, AddressList, BlockId, CompactTxStreamerClient, GetAddressUtxosArg,
|
broadcast_tx, build_tx, AddressList, BlockId, BlockRange, CompactTxStreamerClient,
|
||||||
GetAddressUtxosReply, Hash, TransparentAddressBlockFilter, TxFilter, BlockRange,
|
GetAddressUtxosArg, GetAddressUtxosReply, Hash, TransparentAddressBlockFilter, TxFilter,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use base58check::FromBase58Check;
|
use base58check::FromBase58Check;
|
||||||
|
@ -25,7 +25,7 @@ use tonic::transport::Channel;
|
||||||
use tonic::Request;
|
use tonic::Request;
|
||||||
use zcash_client_backend::encoding::encode_transparent_address;
|
use zcash_client_backend::encoding::encode_transparent_address;
|
||||||
use zcash_params::coin::get_branch;
|
use zcash_params::coin::get_branch;
|
||||||
use zcash_primitives::consensus::{Network, Parameters, NetworkUpgrade};
|
use zcash_primitives::consensus::{Network, NetworkUpgrade, Parameters};
|
||||||
use zcash_primitives::legacy::TransparentAddress;
|
use zcash_primitives::legacy::TransparentAddress;
|
||||||
use zcash_primitives::memo::Memo;
|
use zcash_primitives::memo::Memo;
|
||||||
use zcash_primitives::transaction::components::OutPoint;
|
use zcash_primitives::transaction::components::OutPoint;
|
||||||
|
@ -178,12 +178,23 @@ pub async fn scan_transparent_accounts(
|
||||||
mut aindex: u32,
|
mut aindex: u32,
|
||||||
gap_limit: usize,
|
gap_limit: usize,
|
||||||
) -> anyhow::Result<Vec<TBalance>> {
|
) -> anyhow::Result<Vec<TBalance>> {
|
||||||
let start: u32 = network.activation_height(NetworkUpgrade::Sapling).unwrap().into();
|
let start: u32 = network
|
||||||
|
.activation_height(NetworkUpgrade::Sapling)
|
||||||
|
.unwrap()
|
||||||
|
.into();
|
||||||
let end = get_latest_height(client).await?;
|
let end = get_latest_height(client).await?;
|
||||||
|
|
||||||
let range = BlockRange {
|
let range = BlockRange {
|
||||||
start: Some(BlockId { height: start as u64, hash: vec![] }),
|
start: Some(BlockId {
|
||||||
end: Some(BlockId { height: end as u64, hash: vec![] }), spam_filter_threshold: 0 };
|
height: start as u64,
|
||||||
|
hash: vec![],
|
||||||
|
}),
|
||||||
|
end: Some(BlockId {
|
||||||
|
height: end as u64,
|
||||||
|
hash: vec![],
|
||||||
|
}),
|
||||||
|
spam_filter_threshold: 0,
|
||||||
|
};
|
||||||
|
|
||||||
let mut addresses = vec![];
|
let mut addresses = vec![];
|
||||||
let mut gap = 0;
|
let mut gap = 0;
|
||||||
|
|
Loading…
Reference in New Issue