Add `get_transparent_balances` to data api.

This commit is contained in:
Kris Nuttycombe 2022-10-25 12:04:02 -06:00
parent 8cb16d878e
commit efa95fcb39
5 changed files with 80 additions and 3 deletions

View File

@ -36,6 +36,7 @@ and this library adheres to Rust's notion of
- `WalletRead::get_all_nullifiers`
- `WalletRead::get_transparent_receivers`
- `WalletRead::get_unspent_transparent_outputs`
- `WalletRead::get_transparent_balances`
- `WalletWrite::create_account`
- `WalletWrite::remove_unmined_tx` (behind the `unstable` feature flag).
- `WalletWrite::get_next_available_address`

View File

@ -216,6 +216,14 @@ pub trait WalletRead {
address: &TransparentAddress,
max_height: BlockHeight,
) -> Result<Vec<WalletTransparentOutput>, Self::Error>;
/// Returns a mapping from transparent receiver to not-yet-shielded UTXO balance,
/// for each address associated with a nonzero balance.
fn get_transparent_balances(
&self,
account: AccountId,
max_height: BlockHeight,
) -> Result<HashMap<TransparentAddress, Amount>, Self::Error>;
}
/// The subset of information that is relevant to this wallet that has been
@ -563,6 +571,14 @@ pub mod testing {
) -> Result<Vec<WalletTransparentOutput>, Self::Error> {
Ok(Vec::new())
}
fn get_transparent_balances(
&self,
_account: AccountId,
_max_height: BlockHeight,
) -> Result<HashMap<TransparentAddress, Amount>, Self::Error> {
Ok(HashMap::new())
}
}
impl WalletWrite for MockWalletDb {

View File

@ -168,6 +168,12 @@ impl From<hdwallet::error::Error> for SqliteClientError {
}
}
impl From<TransparentCodecError> for SqliteClientError {
fn from(e: TransparentCodecError) -> Self {
SqliteClientError::TransparentAddress(e)
}
}
impl From<zcash_primitives::memo::Error> for SqliteClientError {
fn from(e: zcash_primitives::memo::Error) -> Self {
SqliteClientError::InvalidMemo(e)

View File

@ -271,6 +271,20 @@ impl<P: consensus::Parameters> WalletRead for WalletDb<P> {
Error::TransparentInputsNotSupported,
));
}
fn get_transparent_balances(
&self,
_account: AccountId,
_max_height: BlockHeight,
) -> Result<HashMap<TransparentAddress, Amount>, Self::Error> {
#[cfg(feature = "transparent-inputs")]
return wallet::get_transparent_balances(self, _account, _max_height);
#[cfg(not(feature = "transparent-inputs"))]
return Err(SqliteClientError::BackendError(
Error::TransparentInputsNotSupported,
));
}
}
impl<'a, P: consensus::Parameters> WalletRead for DataConnStmtCache<'a, P> {
@ -391,6 +405,14 @@ impl<'a, P: consensus::Parameters> WalletRead for DataConnStmtCache<'a, P> {
self.wallet_db
.get_unspent_transparent_outputs(address, max_height)
}
fn get_transparent_balances(
&self,
account: AccountId,
max_height: BlockHeight,
) -> Result<HashMap<TransparentAddress, Amount>, Self::Error> {
self.wallet_db.get_transparent_balances(account, max_height)
}
}
impl<'a, P: consensus::Parameters> DataConnStmtCache<'a, P> {

View File

@ -267,8 +267,8 @@ pub(crate) fn get_transparent_receivers<P: consensus::Parameters>(
let mut ret = HashMap::new();
// Get all UAs derived
let mut ua_query =
conn.prepare("SELECT address, diversifier_index_be FROM addresses WHERE account = :account")?;
let mut ua_query = conn
.prepare("SELECT address, diversifier_index_be FROM addresses WHERE account = :account")?;
let mut rows = ua_query.query(named_params![":account": &u32::from(account)])?;
while let Some(row) = rows.next()? {
@ -966,7 +966,7 @@ pub(crate) fn get_unspent_transparent_outputs<P: consensus::Parameters>(
ON tx.id_tx = u.spent_in_tx
WHERE u.address = ?
AND u.height <= ?
AND block IS NULL",
AND tx.block IS NULL",
)?;
let addr_str = address.encode(&wdb.params);
@ -1004,6 +1004,38 @@ pub(crate) fn get_unspent_transparent_outputs<P: consensus::Parameters>(
Ok(utxos)
}
/// Returns the unspent balance for each transparent address associated with the specified account,
/// such that the block that included the transaction was mined at a height less than or equal to
/// the provided `max_height`.
#[cfg(feature = "transparent-inputs")]
pub(crate) fn get_transparent_balances<P: consensus::Parameters>(
wdb: &WalletDb<P>,
account: AccountId,
max_height: BlockHeight,
) -> Result<HashMap<TransparentAddress, Amount>, SqliteClientError> {
let mut stmt_blocks = wdb.conn.prepare(
"SELECT u.address, SUM(u.value_zat)
FROM utxos u
LEFT OUTER JOIN transactions tx
ON tx.id_tx = u.spent_in_tx
WHERE u.received_by_accountt = ?
AND u.height <= ?
AND tx.block IS NULL",
)?;
let mut res = HashMap::new();
let mut rows = stmt_blocks.query(params![u32::from(account), u32::from(max_height)])?;
while let Some(row) = rows.next()? {
let taddr_str: String = row.get(0)?;
let taddr = TransparentAddress::decode(&wdb.params, &taddr_str)?;
let value = Amount::from_i64(row.get(1)?).unwrap();
res.insert(taddr, value);
}
Ok(res)
}
/// Inserts information about a scanned block into the database.
#[deprecated(
note = "This function will be removed in a future release. Use zcash_client_backend::data_api::WalletWrite::advance_by_block instead."