Add more information to v_transactions, v_sent_tx, and v_received_tx
This adds sent and received note count information, transaction fees, account information, and makes the information returned about sent notes and received notes consistent with one another.
This commit is contained in:
parent
f689018fcd
commit
85390cb8ce
|
@ -380,7 +380,7 @@ mod tests {
|
||||||
"CREATE TABLE \"sent_notes\" (
|
"CREATE TABLE \"sent_notes\" (
|
||||||
id_note INTEGER PRIMARY KEY,
|
id_note INTEGER PRIMARY KEY,
|
||||||
tx INTEGER NOT NULL,
|
tx INTEGER NOT NULL,
|
||||||
output_pool INTEGER NOT NULL ,
|
output_pool INTEGER NOT NULL,
|
||||||
output_index INTEGER NOT NULL,
|
output_index INTEGER NOT NULL,
|
||||||
from_account INTEGER NOT NULL,
|
from_account INTEGER NOT NULL,
|
||||||
to_address TEXT,
|
to_address TEXT,
|
||||||
|
@ -438,16 +438,22 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let expected_views = vec![
|
let expected_views = vec![
|
||||||
|
// v_transactions
|
||||||
"CREATE VIEW v_transactions AS
|
"CREATE VIEW v_transactions AS
|
||||||
SELECT id_tx,
|
SELECT notes.id_tx,
|
||||||
mined_height,
|
notes.mined_height,
|
||||||
tx_index,
|
notes.tx_index,
|
||||||
txid,
|
notes.txid,
|
||||||
expiry_height,
|
notes.expiry_height,
|
||||||
raw,
|
notes.raw,
|
||||||
SUM(value) + MAX(fee) AS net_value,
|
SUM(notes.value) + MAX(notes.fee) AS net_value,
|
||||||
SUM(is_change) > 0 AS has_change,
|
MAX(notes.fee) AS fee_paid,
|
||||||
SUM(memo_present) AS memo_count
|
SUM(notes.is_wallet_internal) > 0 AS is_wallet_internal,
|
||||||
|
SUM(notes.is_change) > 0 AS has_change,
|
||||||
|
SUM(notes.sent_count) AS sent_note_count,
|
||||||
|
SUM(notes.received_count) AS received_note_count,
|
||||||
|
SUM(notes.memo_present) AS memo_count,
|
||||||
|
blocks.time AS block_time
|
||||||
FROM (
|
FROM (
|
||||||
SELECT transactions.id_tx AS id_tx,
|
SELECT transactions.id_tx AS id_tx,
|
||||||
transactions.block AS mined_height,
|
transactions.block AS mined_height,
|
||||||
|
@ -460,7 +466,16 @@ mod tests {
|
||||||
WHEN received_notes.is_change THEN 0
|
WHEN received_notes.is_change THEN 0
|
||||||
ELSE value
|
ELSE value
|
||||||
END AS value,
|
END AS value,
|
||||||
received_notes.is_change AS is_change,
|
0 AS is_wallet_internal,
|
||||||
|
CASE
|
||||||
|
WHEN received_notes.is_change THEN 1
|
||||||
|
ELSE 0
|
||||||
|
END AS is_change,
|
||||||
|
CASE
|
||||||
|
WHEN received_notes.is_change THEN 0
|
||||||
|
ELSE 1
|
||||||
|
END AS received_count,
|
||||||
|
0 AS sent_count,
|
||||||
CASE
|
CASE
|
||||||
WHEN received_notes.memo IS NULL THEN 0
|
WHEN received_notes.memo IS NULL THEN 0
|
||||||
ELSE 1
|
ELSE 1
|
||||||
|
@ -476,20 +491,31 @@ mod tests {
|
||||||
transactions.raw AS raw,
|
transactions.raw AS raw,
|
||||||
transactions.fee AS fee,
|
transactions.fee AS fee,
|
||||||
-sent_notes.value AS value,
|
-sent_notes.value AS value,
|
||||||
false AS is_change,
|
CASE
|
||||||
|
WHEN sent_notes.from_account = sent_notes.to_account THEN 1
|
||||||
|
ELSE 0
|
||||||
|
END AS is_wallet_internal,
|
||||||
|
0 AS is_change,
|
||||||
|
0 AS received_count,
|
||||||
|
1 AS sent_count,
|
||||||
CASE
|
CASE
|
||||||
WHEN sent_notes.memo IS NULL THEN 0
|
WHEN sent_notes.memo IS NULL THEN 0
|
||||||
ELSE 1
|
ELSE 1
|
||||||
END AS memo_present
|
END AS memo_present
|
||||||
FROM transactions
|
FROM transactions
|
||||||
JOIN sent_notes ON transactions.id_tx = sent_notes.tx
|
JOIN sent_notes ON transactions.id_tx = sent_notes.tx
|
||||||
)
|
) AS notes
|
||||||
GROUP BY id_tx",
|
LEFT JOIN blocks ON notes.mined_height = blocks.height
|
||||||
|
GROUP BY notes.id_tx",
|
||||||
|
// v_tx_received
|
||||||
"CREATE VIEW v_tx_received AS
|
"CREATE VIEW v_tx_received AS
|
||||||
SELECT transactions.id_tx AS id_tx,
|
SELECT transactions.id_tx AS id_tx,
|
||||||
transactions.block AS mined_height,
|
transactions.block AS mined_height,
|
||||||
transactions.tx_index AS tx_index,
|
transactions.tx_index AS tx_index,
|
||||||
transactions.txid AS txid,
|
transactions.txid AS txid,
|
||||||
|
transactions.expiry_height AS expiry_height,
|
||||||
|
transactions.raw AS raw,
|
||||||
|
MAX(received_notes.account) AS received_by_account,
|
||||||
SUM(received_notes.value) AS received_total,
|
SUM(received_notes.value) AS received_total,
|
||||||
COUNT(received_notes.id_note) AS received_note_count,
|
COUNT(received_notes.id_note) AS received_note_count,
|
||||||
SUM(
|
SUM(
|
||||||
|
@ -504,7 +530,8 @@ mod tests {
|
||||||
ON transactions.id_tx = received_notes.tx
|
ON transactions.id_tx = received_notes.tx
|
||||||
LEFT JOIN blocks
|
LEFT JOIN blocks
|
||||||
ON transactions.block = blocks.height
|
ON transactions.block = blocks.height
|
||||||
GROUP BY received_notes.tx",
|
GROUP BY received_notes.tx, received_notes.account",
|
||||||
|
// v_tx_received
|
||||||
"CREATE VIEW v_tx_sent AS
|
"CREATE VIEW v_tx_sent AS
|
||||||
SELECT transactions.id_tx AS id_tx,
|
SELECT transactions.id_tx AS id_tx,
|
||||||
transactions.block AS mined_height,
|
transactions.block AS mined_height,
|
||||||
|
@ -512,6 +539,7 @@ mod tests {
|
||||||
transactions.txid AS txid,
|
transactions.txid AS txid,
|
||||||
transactions.expiry_height AS expiry_height,
|
transactions.expiry_height AS expiry_height,
|
||||||
transactions.raw AS raw,
|
transactions.raw AS raw,
|
||||||
|
MAX(sent_notes.from_account) AS sent_from_account,
|
||||||
SUM(sent_notes.value) AS sent_total,
|
SUM(sent_notes.value) AS sent_total,
|
||||||
COUNT(sent_notes.id_note) AS sent_note_count,
|
COUNT(sent_notes.id_note) AS sent_note_count,
|
||||||
SUM(
|
SUM(
|
||||||
|
@ -526,7 +554,7 @@ mod tests {
|
||||||
ON transactions.id_tx = sent_notes.tx
|
ON transactions.id_tx = sent_notes.tx
|
||||||
LEFT JOIN blocks
|
LEFT JOIN blocks
|
||||||
ON transactions.block = blocks.height
|
ON transactions.block = blocks.height
|
||||||
GROUP BY sent_notes.tx",
|
GROUP BY sent_notes.tx, sent_notes.from_account",
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut views_query = db_data
|
let mut views_query = db_data
|
||||||
|
|
|
@ -16,6 +16,15 @@ pub(super) fn all_migrations<P: consensus::Parameters + 'static>(
|
||||||
params: &P,
|
params: &P,
|
||||||
seed: Option<SecretVec<u8>>,
|
seed: Option<SecretVec<u8>>,
|
||||||
) -> Vec<Box<dyn RusqliteMigration<Error = WalletMigrationError>>> {
|
) -> Vec<Box<dyn RusqliteMigration<Error = WalletMigrationError>>> {
|
||||||
|
// initial_setup
|
||||||
|
// / \
|
||||||
|
// utxos_table ufvk_support ----------
|
||||||
|
// \ \ \
|
||||||
|
// \ addresses_table sent_notes_to_internal
|
||||||
|
// \ / /
|
||||||
|
// add_utxo_account /
|
||||||
|
// \ /
|
||||||
|
// add_transaction_views
|
||||||
vec![
|
vec![
|
||||||
Box::new(initial_setup::Migration {}),
|
Box::new(initial_setup::Migration {}),
|
||||||
Box::new(utxos_table::Migration {}),
|
Box::new(utxos_table::Migration {}),
|
||||||
|
@ -26,12 +35,12 @@ pub(super) fn all_migrations<P: consensus::Parameters + 'static>(
|
||||||
Box::new(addresses_table::Migration {
|
Box::new(addresses_table::Migration {
|
||||||
params: params.clone(),
|
params: params.clone(),
|
||||||
}),
|
}),
|
||||||
Box::new(add_transaction_views::Migration {
|
|
||||||
params: params.clone(),
|
|
||||||
}),
|
|
||||||
Box::new(add_utxo_account::Migration {
|
Box::new(add_utxo_account::Migration {
|
||||||
_params: params.clone(),
|
_params: params.clone(),
|
||||||
}),
|
}),
|
||||||
Box::new(sent_notes_to_internal::Migration {}),
|
Box::new(sent_notes_to_internal::Migration {}),
|
||||||
|
Box::new(add_transaction_views::Migration {
|
||||||
|
params: params.clone(),
|
||||||
|
}),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use zcash_primitives::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{ufvk_support, utxos_table};
|
use super::{add_utxo_account, sent_notes_to_internal};
|
||||||
use crate::wallet::init::WalletMigrationError;
|
use crate::wallet::init::WalletMigrationError;
|
||||||
|
|
||||||
pub(super) const MIGRATION_ID: Uuid = Uuid::from_fields(
|
pub(super) const MIGRATION_ID: Uuid = Uuid::from_fields(
|
||||||
|
@ -34,7 +34,7 @@ impl<P> schemer::Migration for Migration<P> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dependencies(&self) -> HashSet<Uuid> {
|
fn dependencies(&self) -> HashSet<Uuid> {
|
||||||
[ufvk_support::MIGRATION_ID, utxos_table::MIGRATION_ID]
|
[add_utxo_account::MIGRATION_ID, sent_notes_to_internal::MIGRATION_ID]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -152,6 +152,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
|
||||||
transactions.txid AS txid,
|
transactions.txid AS txid,
|
||||||
transactions.expiry_height AS expiry_height,
|
transactions.expiry_height AS expiry_height,
|
||||||
transactions.raw AS raw,
|
transactions.raw AS raw,
|
||||||
|
MAX(sent_notes.from_account) AS sent_from_account,
|
||||||
SUM(sent_notes.value) AS sent_total,
|
SUM(sent_notes.value) AS sent_total,
|
||||||
COUNT(sent_notes.id_note) AS sent_note_count,
|
COUNT(sent_notes.id_note) AS sent_note_count,
|
||||||
SUM(
|
SUM(
|
||||||
|
@ -166,12 +167,18 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
|
||||||
ON transactions.id_tx = sent_notes.tx
|
ON transactions.id_tx = sent_notes.tx
|
||||||
LEFT JOIN blocks
|
LEFT JOIN blocks
|
||||||
ON transactions.block = blocks.height
|
ON transactions.block = blocks.height
|
||||||
GROUP BY sent_notes.tx;
|
GROUP BY sent_notes.tx, sent_notes.from_account;",
|
||||||
CREATE VIEW v_tx_received AS
|
)?;
|
||||||
|
|
||||||
|
transaction.execute_batch(
|
||||||
|
"CREATE VIEW v_tx_received AS
|
||||||
SELECT transactions.id_tx AS id_tx,
|
SELECT transactions.id_tx AS id_tx,
|
||||||
transactions.block AS mined_height,
|
transactions.block AS mined_height,
|
||||||
transactions.tx_index AS tx_index,
|
transactions.tx_index AS tx_index,
|
||||||
transactions.txid AS txid,
|
transactions.txid AS txid,
|
||||||
|
transactions.expiry_height AS expiry_height,
|
||||||
|
transactions.raw AS raw,
|
||||||
|
MAX(received_notes.account) AS received_by_account,
|
||||||
SUM(received_notes.value) AS received_total,
|
SUM(received_notes.value) AS received_total,
|
||||||
COUNT(received_notes.id_note) AS received_note_count,
|
COUNT(received_notes.id_note) AS received_note_count,
|
||||||
SUM(
|
SUM(
|
||||||
|
@ -186,17 +193,25 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
|
||||||
ON transactions.id_tx = received_notes.tx
|
ON transactions.id_tx = received_notes.tx
|
||||||
LEFT JOIN blocks
|
LEFT JOIN blocks
|
||||||
ON transactions.block = blocks.height
|
ON transactions.block = blocks.height
|
||||||
GROUP BY received_notes.tx;
|
GROUP BY received_notes.tx, received_notes.account;",
|
||||||
CREATE VIEW v_transactions AS
|
)?;
|
||||||
SELECT id_tx,
|
|
||||||
mined_height,
|
transaction.execute_batch(
|
||||||
tx_index,
|
"CREATE VIEW v_transactions AS
|
||||||
txid,
|
SELECT notes.id_tx,
|
||||||
expiry_height,
|
notes.mined_height,
|
||||||
raw,
|
notes.tx_index,
|
||||||
SUM(value) + MAX(fee) AS net_value,
|
notes.txid,
|
||||||
SUM(is_change) > 0 AS has_change,
|
notes.expiry_height,
|
||||||
SUM(memo_present) AS memo_count
|
notes.raw,
|
||||||
|
SUM(notes.value) + MAX(notes.fee) AS net_value,
|
||||||
|
MAX(notes.fee) AS fee_paid,
|
||||||
|
SUM(notes.is_wallet_internal) > 0 AS is_wallet_internal,
|
||||||
|
SUM(notes.is_change) > 0 AS has_change,
|
||||||
|
SUM(notes.sent_count) AS sent_note_count,
|
||||||
|
SUM(notes.received_count) AS received_note_count,
|
||||||
|
SUM(notes.memo_present) AS memo_count,
|
||||||
|
blocks.time AS block_time
|
||||||
FROM (
|
FROM (
|
||||||
SELECT transactions.id_tx AS id_tx,
|
SELECT transactions.id_tx AS id_tx,
|
||||||
transactions.block AS mined_height,
|
transactions.block AS mined_height,
|
||||||
|
@ -209,7 +224,16 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
|
||||||
WHEN received_notes.is_change THEN 0
|
WHEN received_notes.is_change THEN 0
|
||||||
ELSE value
|
ELSE value
|
||||||
END AS value,
|
END AS value,
|
||||||
received_notes.is_change AS is_change,
|
0 AS is_wallet_internal,
|
||||||
|
CASE
|
||||||
|
WHEN received_notes.is_change THEN 1
|
||||||
|
ELSE 0
|
||||||
|
END AS is_change,
|
||||||
|
CASE
|
||||||
|
WHEN received_notes.is_change THEN 0
|
||||||
|
ELSE 1
|
||||||
|
END AS received_count,
|
||||||
|
0 AS sent_count,
|
||||||
CASE
|
CASE
|
||||||
WHEN received_notes.memo IS NULL THEN 0
|
WHEN received_notes.memo IS NULL THEN 0
|
||||||
ELSE 1
|
ELSE 1
|
||||||
|
@ -225,15 +249,22 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
|
||||||
transactions.raw AS raw,
|
transactions.raw AS raw,
|
||||||
transactions.fee AS fee,
|
transactions.fee AS fee,
|
||||||
-sent_notes.value AS value,
|
-sent_notes.value AS value,
|
||||||
false AS is_change,
|
CASE
|
||||||
|
WHEN sent_notes.from_account = sent_notes.to_account THEN 1
|
||||||
|
ELSE 0
|
||||||
|
END AS is_wallet_internal,
|
||||||
|
0 AS is_change,
|
||||||
|
0 AS received_count,
|
||||||
|
1 AS sent_count,
|
||||||
CASE
|
CASE
|
||||||
WHEN sent_notes.memo IS NULL THEN 0
|
WHEN sent_notes.memo IS NULL THEN 0
|
||||||
ELSE 1
|
ELSE 1
|
||||||
END AS memo_present
|
END AS memo_present
|
||||||
FROM transactions
|
FROM transactions
|
||||||
JOIN sent_notes ON transactions.id_tx = sent_notes.tx
|
JOIN sent_notes ON transactions.id_tx = sent_notes.tx
|
||||||
)
|
) AS notes
|
||||||
GROUP BY id_tx;",
|
LEFT JOIN blocks ON notes.mined_height = blocks.height
|
||||||
|
GROUP BY notes.id_tx;",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -7,7 +7,7 @@ use schemer;
|
||||||
use schemer_rusqlite::RusqliteMigration;
|
use schemer_rusqlite::RusqliteMigration;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{addresses_table, utxos_table};
|
use super::{ufvk_support};
|
||||||
use crate::wallet::init::WalletMigrationError;
|
use crate::wallet::init::WalletMigrationError;
|
||||||
|
|
||||||
/// This migration adds the `to_account` field to the `sent_notes` table.
|
/// This migration adds the `to_account` field to the `sent_notes` table.
|
||||||
|
@ -28,7 +28,7 @@ impl schemer::Migration for Migration {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dependencies(&self) -> HashSet<Uuid> {
|
fn dependencies(&self) -> HashSet<Uuid> {
|
||||||
[utxos_table::MIGRATION_ID, addresses_table::MIGRATION_ID]
|
[ufvk_support::MIGRATION_ID]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ impl RusqliteMigration for Migration {
|
||||||
"CREATE TABLE sent_notes_new (
|
"CREATE TABLE sent_notes_new (
|
||||||
id_note INTEGER PRIMARY KEY,
|
id_note INTEGER PRIMARY KEY,
|
||||||
tx INTEGER NOT NULL,
|
tx INTEGER NOT NULL,
|
||||||
output_pool INTEGER NOT NULL ,
|
output_pool INTEGER NOT NULL,
|
||||||
output_index INTEGER NOT NULL,
|
output_index INTEGER NOT NULL,
|
||||||
from_account INTEGER NOT NULL,
|
from_account INTEGER NOT NULL,
|
||||||
to_address TEXT,
|
to_address TEXT,
|
||||||
|
|
|
@ -19,7 +19,7 @@ use zcash_primitives::legacy::keys::IncomingViewingKey;
|
||||||
use zcash_client_backend::encoding::AddressCodec;
|
use zcash_client_backend::encoding::AddressCodec;
|
||||||
|
|
||||||
use crate::wallet::{
|
use crate::wallet::{
|
||||||
init::{migrations::utxos_table, WalletMigrationError},
|
init::{migrations::initial_setup, WalletMigrationError},
|
||||||
pool_code,
|
pool_code,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ impl<P> schemer::Migration for Migration<P> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dependencies(&self) -> HashSet<Uuid> {
|
fn dependencies(&self) -> HashSet<Uuid> {
|
||||||
[utxos_table::MIGRATION_ID].into_iter().collect()
|
[initial_setup::MIGRATION_ID].into_iter().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn description(&self) -> &'static str {
|
fn description(&self) -> &'static str {
|
||||||
|
|
Loading…
Reference in New Issue