zcash_client_sqlite: Fix ambiguities in transaction views
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
This commit is contained in:
parent
1775f6525b
commit
8b8757ce65
|
@ -63,6 +63,7 @@ use zcash_primitives::{
|
|||
zip32::DiversifierIndex,
|
||||
};
|
||||
use zcash_protocol::local_consensus::LocalNetwork;
|
||||
use zcash_protocol::value::{ZatBalance, Zatoshis};
|
||||
|
||||
use crate::{
|
||||
chain::init::init_cache_database,
|
||||
|
@ -958,6 +959,105 @@ impl<Cache> TestState<Cache> {
|
|||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Returns a vector of transaction summaries
|
||||
pub(crate) fn get_tx_history(
|
||||
&self,
|
||||
) -> Result<Vec<TransactionSummary<AccountId>>, SqliteClientError> {
|
||||
let mut stmt = self.wallet().conn.prepare_cached(
|
||||
"SELECT *
|
||||
FROM v_transactions
|
||||
ORDER BY mined_height DESC, tx_index DESC",
|
||||
)?;
|
||||
|
||||
let results = stmt
|
||||
.query_and_then::<TransactionSummary<AccountId>, SqliteClientError, _, _>([], |row| {
|
||||
Ok(TransactionSummary {
|
||||
account_id: AccountId(row.get("account_id")?),
|
||||
txid: TxId::from_bytes(row.get("txid")?),
|
||||
expiry_height: row
|
||||
.get::<_, Option<u32>>("expiry_height")?
|
||||
.map(BlockHeight::from),
|
||||
mined_height: row
|
||||
.get::<_, Option<u32>>("mined_height")?
|
||||
.map(BlockHeight::from),
|
||||
account_value_delta: ZatBalance::from_i64(row.get("account_balance_delta")?)?,
|
||||
fee_paid: row
|
||||
.get::<_, Option<i64>>("fee_paid")?
|
||||
.map(Zatoshis::from_nonnegative_i64)
|
||||
.transpose()?,
|
||||
has_change: row.get("has_change")?,
|
||||
sent_note_count: row.get("sent_note_count")?,
|
||||
received_note_count: row.get("received_note_count")?,
|
||||
memo_count: row.get("memo_count")?,
|
||||
expired_unmined: row.get("expired_unmined")?,
|
||||
})
|
||||
})?
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(results)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct TransactionSummary<AccountId> {
|
||||
account_id: AccountId,
|
||||
txid: TxId,
|
||||
expiry_height: Option<BlockHeight>,
|
||||
mined_height: Option<BlockHeight>,
|
||||
account_value_delta: ZatBalance,
|
||||
fee_paid: Option<Zatoshis>,
|
||||
has_change: bool,
|
||||
sent_note_count: usize,
|
||||
received_note_count: usize,
|
||||
memo_count: usize,
|
||||
expired_unmined: bool,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<AccountId> TransactionSummary<AccountId> {
|
||||
pub(crate) fn account_id(&self) -> &AccountId {
|
||||
&self.account_id
|
||||
}
|
||||
|
||||
pub(crate) fn txid(&self) -> TxId {
|
||||
self.txid
|
||||
}
|
||||
|
||||
pub(crate) fn expiry_height(&self) -> Option<BlockHeight> {
|
||||
self.expiry_height
|
||||
}
|
||||
|
||||
pub(crate) fn mined_height(&self) -> Option<BlockHeight> {
|
||||
self.mined_height
|
||||
}
|
||||
|
||||
pub(crate) fn account_value_delta(&self) -> ZatBalance {
|
||||
self.account_value_delta
|
||||
}
|
||||
|
||||
pub(crate) fn fee_paid(&self) -> Option<Zatoshis> {
|
||||
self.fee_paid
|
||||
}
|
||||
|
||||
pub(crate) fn has_change(&self) -> bool {
|
||||
self.has_change
|
||||
}
|
||||
|
||||
pub(crate) fn sent_note_count(&self) -> usize {
|
||||
self.sent_note_count
|
||||
}
|
||||
|
||||
pub(crate) fn received_note_count(&self) -> usize {
|
||||
self.received_note_count
|
||||
}
|
||||
|
||||
pub(crate) fn expired_unmined(&self) -> bool {
|
||||
self.expired_unmined
|
||||
}
|
||||
|
||||
pub(crate) fn memo_count(&self) -> usize {
|
||||
self.memo_count
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait used by tests that require a full viewing key.
|
||||
|
|
|
@ -271,6 +271,9 @@ pub(crate) fn send_single_step_proposed_transfer<T: ShieldedPoolTester>() {
|
|||
.get_memo(NoteId::new(sent_tx_id, T::SHIELDED_PROTOCOL, 12345)),
|
||||
Ok(None)
|
||||
);
|
||||
|
||||
let tx_history = st.get_tx_history().unwrap();
|
||||
assert_eq!(tx_history.len(), 2);
|
||||
}
|
||||
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
|
|
|
@ -552,14 +552,14 @@ mod tests {
|
|||
// v_received_notes
|
||||
"CREATE VIEW v_received_notes AS
|
||||
SELECT
|
||||
id,
|
||||
tx,
|
||||
sapling_received_notes.id AS id_within_pool_table,
|
||||
sapling_received_notes.tx,
|
||||
2 AS pool,
|
||||
sapling_received_notes.output_index AS output_index,
|
||||
account_id,
|
||||
value,
|
||||
sapling_received_notes.value,
|
||||
is_change,
|
||||
memo,
|
||||
sapling_received_notes.memo,
|
||||
spent,
|
||||
sent_notes.id AS sent_note_id
|
||||
FROM sapling_received_notes
|
||||
|
@ -568,14 +568,14 @@ mod tests {
|
|||
(sapling_received_notes.tx, 2, sapling_received_notes.output_index)
|
||||
UNION
|
||||
SELECT
|
||||
id,
|
||||
tx,
|
||||
orchard_received_notes.id AS id_within_pool_table,
|
||||
orchard_received_notes.tx,
|
||||
3 AS pool,
|
||||
orchard_received_notes.action_index AS output_index,
|
||||
account_id,
|
||||
value,
|
||||
orchard_received_notes.value,
|
||||
is_change,
|
||||
memo,
|
||||
orchard_received_notes.memo,
|
||||
spent,
|
||||
sent_notes.id AS sent_note_id
|
||||
FROM orchard_received_notes
|
||||
|
@ -650,11 +650,12 @@ mod tests {
|
|||
"CREATE VIEW v_transactions AS
|
||||
WITH
|
||||
notes AS (
|
||||
SELECT v_received_notes.id AS id,
|
||||
v_received_notes.account_id AS account_id,
|
||||
-- Shielded notes received in this transaction
|
||||
SELECT v_received_notes.account_id AS account_id,
|
||||
transactions.block AS block,
|
||||
transactions.txid AS txid,
|
||||
v_received_notes.pool AS pool,
|
||||
id_within_pool_table,
|
||||
v_received_notes.value AS value,
|
||||
CASE
|
||||
WHEN v_received_notes.is_change THEN 1
|
||||
|
@ -673,22 +674,24 @@ mod tests {
|
|||
JOIN transactions
|
||||
ON transactions.id_tx = v_received_notes.tx
|
||||
UNION
|
||||
SELECT utxos.id AS id,
|
||||
utxos.received_by_account_id AS account_id,
|
||||
-- Transparent TXOs received in this transaction
|
||||
SELECT utxos.received_by_account_id AS account_id,
|
||||
utxos.height AS block,
|
||||
utxos.prevout_txid AS txid,
|
||||
0 AS pool,
|
||||
utxos.id AS id_within_pool_table,
|
||||
utxos.value_zat AS value,
|
||||
0 AS is_change,
|
||||
1 AS received_count,
|
||||
0 AS memo_present
|
||||
FROM utxos
|
||||
UNION
|
||||
SELECT v_received_notes.id AS id,
|
||||
v_received_notes.account_id AS account_id,
|
||||
-- Shielded notes spent in this transaction
|
||||
SELECT v_received_notes.account_id AS account_id,
|
||||
transactions.block AS block,
|
||||
transactions.txid AS txid,
|
||||
v_received_notes.pool AS pool,
|
||||
id_within_pool_table,
|
||||
-v_received_notes.value AS value,
|
||||
0 AS is_change,
|
||||
0 AS received_count,
|
||||
|
@ -697,11 +700,12 @@ mod tests {
|
|||
JOIN transactions
|
||||
ON transactions.id_tx = v_received_notes.spent
|
||||
UNION
|
||||
SELECT utxos.id AS id,
|
||||
utxos.received_by_account_id AS account_id,
|
||||
-- Transparent TXOs spent in this transaction
|
||||
SELECT utxos.received_by_account_id AS account_id,
|
||||
transactions.block AS block,
|
||||
transactions.txid AS txid,
|
||||
0 AS pool,
|
||||
utxos.id AS id_within_pool_table,
|
||||
-utxos.value_zat AS value,
|
||||
0 AS is_change,
|
||||
0 AS received_count,
|
||||
|
@ -710,6 +714,8 @@ mod tests {
|
|||
JOIN transactions
|
||||
ON transactions.id_tx = utxos.spent_in_tx
|
||||
),
|
||||
-- Obtain a count of the notes that the wallet created in each transaction,
|
||||
-- not counting change notes.
|
||||
sent_note_counts AS (
|
||||
SELECT sent_notes.from_account_id AS account_id,
|
||||
transactions.txid AS txid,
|
||||
|
|
|
@ -70,14 +70,14 @@ impl RusqliteMigration for Migration {
|
|||
&format!(
|
||||
"CREATE VIEW v_received_notes AS
|
||||
SELECT
|
||||
id,
|
||||
tx,
|
||||
sapling_received_notes.id AS id_within_pool_table,
|
||||
sapling_received_notes.tx,
|
||||
{sapling_pool_code} AS pool,
|
||||
sapling_received_notes.output_index AS output_index,
|
||||
account_id,
|
||||
value,
|
||||
sapling_received_notes.value,
|
||||
is_change,
|
||||
memo,
|
||||
sapling_received_notes.memo,
|
||||
spent,
|
||||
sent_notes.id AS sent_note_id
|
||||
FROM sapling_received_notes
|
||||
|
@ -86,14 +86,14 @@ impl RusqliteMigration for Migration {
|
|||
(sapling_received_notes.tx, {sapling_pool_code}, sapling_received_notes.output_index)
|
||||
UNION
|
||||
SELECT
|
||||
id,
|
||||
tx,
|
||||
orchard_received_notes.id AS id_within_pool_table,
|
||||
orchard_received_notes.tx,
|
||||
{orchard_pool_code} AS pool,
|
||||
orchard_received_notes.action_index AS output_index,
|
||||
account_id,
|
||||
value,
|
||||
orchard_received_notes.value,
|
||||
is_change,
|
||||
memo,
|
||||
orchard_received_notes.memo,
|
||||
spent,
|
||||
sent_notes.id AS sent_note_id
|
||||
FROM orchard_received_notes
|
||||
|
@ -110,11 +110,12 @@ impl RusqliteMigration for Migration {
|
|||
CREATE VIEW v_transactions AS
|
||||
WITH
|
||||
notes AS (
|
||||
SELECT v_received_notes.id AS id,
|
||||
v_received_notes.account_id AS account_id,
|
||||
-- Shielded notes received in this transaction
|
||||
SELECT v_received_notes.account_id AS account_id,
|
||||
transactions.block AS block,
|
||||
transactions.txid AS txid,
|
||||
v_received_notes.pool AS pool,
|
||||
id_within_pool_table,
|
||||
v_received_notes.value AS value,
|
||||
CASE
|
||||
WHEN v_received_notes.is_change THEN 1
|
||||
|
@ -133,22 +134,24 @@ impl RusqliteMigration for Migration {
|
|||
JOIN transactions
|
||||
ON transactions.id_tx = v_received_notes.tx
|
||||
UNION
|
||||
SELECT utxos.id AS id,
|
||||
utxos.received_by_account_id AS account_id,
|
||||
-- Transparent TXOs received in this transaction
|
||||
SELECT utxos.received_by_account_id AS account_id,
|
||||
utxos.height AS block,
|
||||
utxos.prevout_txid AS txid,
|
||||
{transparent_pool_code} AS pool,
|
||||
utxos.id AS id_within_pool_table,
|
||||
utxos.value_zat AS value,
|
||||
0 AS is_change,
|
||||
1 AS received_count,
|
||||
0 AS memo_present
|
||||
FROM utxos
|
||||
UNION
|
||||
SELECT v_received_notes.id AS id,
|
||||
v_received_notes.account_id AS account_id,
|
||||
-- Shielded notes spent in this transaction
|
||||
SELECT v_received_notes.account_id AS account_id,
|
||||
transactions.block AS block,
|
||||
transactions.txid AS txid,
|
||||
v_received_notes.pool AS pool,
|
||||
id_within_pool_table,
|
||||
-v_received_notes.value AS value,
|
||||
0 AS is_change,
|
||||
0 AS received_count,
|
||||
|
@ -157,11 +160,12 @@ impl RusqliteMigration for Migration {
|
|||
JOIN transactions
|
||||
ON transactions.id_tx = v_received_notes.spent
|
||||
UNION
|
||||
SELECT utxos.id AS id,
|
||||
utxos.received_by_account_id AS account_id,
|
||||
-- Transparent TXOs spent in this transaction
|
||||
SELECT utxos.received_by_account_id AS account_id,
|
||||
transactions.block AS block,
|
||||
transactions.txid AS txid,
|
||||
{transparent_pool_code} AS pool,
|
||||
utxos.id AS id_within_pool_table,
|
||||
-utxos.value_zat AS value,
|
||||
0 AS is_change,
|
||||
0 AS received_count,
|
||||
|
@ -170,6 +174,8 @@ impl RusqliteMigration for Migration {
|
|||
JOIN transactions
|
||||
ON transactions.id_tx = utxos.spent_in_tx
|
||||
),
|
||||
-- Obtain a count of the notes that the wallet created in each transaction,
|
||||
-- not counting change notes.
|
||||
sent_note_counts AS (
|
||||
SELECT sent_notes.from_account_id AS account_id,
|
||||
transactions.txid AS txid,
|
||||
|
|
Loading…
Reference in New Issue