diff --git a/rust-libs/duniter-dbs-read-ops/src/find_inputs.rs b/rust-libs/duniter-dbs-read-ops/src/find_inputs.rs index 86104cc150a523d31bf2ca31841dd74217e99b18..c311da7e46323d78d7ed547511d970e14c92edc5 100644 --- a/rust-libs/duniter-dbs-read-ops/src/find_inputs.rs +++ b/rust-libs/duniter-dbs-read-ops/src/find_inputs.rs @@ -15,7 +15,7 @@ use crate::{ uds_of_pubkey::UdsWithSum, - utxos::{UtxoIdWithBlockNumber, UtxosWithSum}, + utxos::{UtxoCursor, UtxosWithSum}, *, }; use dubp::{documents::transaction::TransactionInputV10, wallet::prelude::*}; @@ -110,11 +110,18 @@ pub fn find_inputs<BcDb: BcV2DbReadable, GvaDb: GvaV1DbReadable, TxsMpDb: TxsMpV &script, )?; inputs.extend(written_utxos.into_iter().map( - |(UtxoIdWithBlockNumber(utxo_id, _), source_amount)| TransactionInputV10 { + |( + UtxoCursor { + tx_hash, + output_index, + .. + }, + source_amount, + )| TransactionInputV10 { amount: source_amount, id: SourceIdV10::Utxo(UtxoIdV10 { - tx_hash: utxo_id.tx_hash, - output_index: utxo_id.output_index, + tx_hash, + output_index: output_index as usize, }), }, )); diff --git a/rust-libs/duniter-dbs-read-ops/src/lib.rs b/rust-libs/duniter-dbs-read-ops/src/lib.rs index 26ca21089c652cad033abfbba93199e9a9abba21..6dfa5f30924e395a700283c55996ba2109587c14 100644 --- a/rust-libs/duniter-dbs-read-ops/src/lib.rs +++ b/rust-libs/duniter-dbs-read-ops/src/lib.rs @@ -43,7 +43,11 @@ use duniter_dbs::{ use resiter::filter::Filter; use resiter::filter_map::FilterMap; use resiter::map::Map; -use std::collections::BTreeSet; +use std::{collections::BTreeSet, str::FromStr}; + +pub(crate) fn wrong_cursor() -> StringErr { + StringErr("wrong cursor".to_owned()) +} #[derive(Clone, Copy, Debug)] pub struct DbsReader; diff --git a/rust-libs/duniter-dbs-read-ops/src/pagination.rs b/rust-libs/duniter-dbs-read-ops/src/pagination.rs index ef9e9a23c1a74fdc71fa56d2b9963ec3d6d5a759..13d3fd1b3482e06d32444fc055c767762fefc545 100644 --- a/rust-libs/duniter-dbs-read-ops/src/pagination.rs +++ b/rust-libs/duniter-dbs-read-ops/src/pagination.rs @@ -75,8 +75,9 @@ where impl<T> Copy for PageInfo<T> where T: Copy {} pub(crate) fn has_next_page< - C: std::fmt::Debug + Default + Ord, - I: DoubleEndedIterator<Item = C>, + 'i, + C: 'static + std::fmt::Debug + Default + Ord, + I: DoubleEndedIterator<Item = &'i C>, >( mut page_cursors: I, last_cursor_opt: Option<C>, @@ -92,7 +93,7 @@ pub(crate) fn has_next_page< page_cursors.next() } { //println!("TMP page_end_cursor={:?}", page_end_cursor); - page_end_cursor != last_cursor + page_end_cursor != &last_cursor } else { page_info.pos.unwrap_or_default() < last_cursor } @@ -105,8 +106,9 @@ pub(crate) fn has_next_page< } pub(crate) fn has_previous_page< - C: std::fmt::Debug + Default + Ord, - I: DoubleEndedIterator<Item = C>, + 'i, + C: 'static + std::fmt::Debug + Default + Ord, + I: DoubleEndedIterator<Item = &'i C>, >( mut page_cursors: I, first_cursor_opt: Option<C>, @@ -121,7 +123,7 @@ pub(crate) fn has_previous_page< } else { page_cursors.next_back() } { - page_start_cursor != first_cursor + page_start_cursor != &first_cursor } else { page_info.pos.unwrap_or_default() > first_cursor } diff --git a/rust-libs/duniter-dbs-read-ops/src/uds_of_pubkey.rs b/rust-libs/duniter-dbs-read-ops/src/uds_of_pubkey.rs index 99ab6565b4c6994038a10c89c4e45b359a3b87ad..adb197a413de0f67ee6779e5c88f3e37d21bf345 100644 --- a/rust-libs/duniter-dbs-read-ops/src/uds_of_pubkey.rs +++ b/rust-libs/duniter-dbs-read-ops/src/uds_of_pubkey.rs @@ -30,7 +30,7 @@ pub fn all_uds_of_pubkey<B: Backend>( bc_db: &BcV2Db<B>, gva_db: &GvaV1Db<B>, pubkey: PublicKey, - page_info: PageInfo<u32>, + page_info: PageInfo<BlockNumber>, ) -> KvResult<PagedData<UdsWithSum>> { ( bc_db.uds_reval(), @@ -67,7 +67,7 @@ pub fn all_uds_of_pubkey<B: Backend>( } Some(pos) => { if page_info.order { - blocks_with_ud.iter(U32BE(pos).., move |it| { + blocks_with_ud.iter(U32BE(pos.0).., move |it| { all_uds_of_pubkey_inner::<B, _>( gva_idty, page_info, @@ -79,7 +79,7 @@ pub fn all_uds_of_pubkey<B: Backend>( } else { let last_ud_opt = blocks_with_ud.iter(.., |it| it.keys().reverse().next_res())?; - blocks_with_ud.iter(..=U32BE(pos), move |it| { + blocks_with_ud.iter(..=U32BE(pos.0), move |it| { all_uds_of_pubkey_inner::<B, _>( gva_idty, page_info, @@ -99,7 +99,7 @@ pub fn all_uds_of_pubkey<B: Backend>( fn all_uds_of_pubkey_inner<B, I>( gva_idty: GvaIdtyDbV1, - page_info: PageInfo<u32>, + page_info: PageInfo<BlockNumber>, blocks_with_ud: I, uds_reval: TxColRo<B::Col, UdsRevalEvent>, last_ud_opt: Option<BlockNumber>, @@ -165,8 +165,8 @@ where Ok(PagedData { has_previous_page: has_previous_page( - uds_with_sum.uds.iter().map(|(bn, _sa)| bn.0), - first_ud.map(|bn| bn.0), + uds_with_sum.uds.iter().map(|(bn, _sa)| bn), + first_ud, page_info, true, ), @@ -177,7 +177,7 @@ where fn filter_blocks_numbers<I: Iterator<Item = KvResult<BlockNumber>>>( gva_idty: GvaIdtyDbV1, - page_info: PageInfo<u32>, + page_info: PageInfo<BlockNumber>, blocks_with_ud: I, ) -> KvResult<Vec<BlockNumber>> { let mut is_member_changes = SmallVec::<[BlockNumber; 4]>::new(); @@ -251,7 +251,7 @@ fn filter_blocks_numbers<I: Iterator<Item = KvResult<BlockNumber>>>( pub fn unspent_uds_of_pubkey<BcDb: BcV2DbReadable>( bc_db: &BcDb, pubkey: PublicKey, - page_info: PageInfo<u32>, + page_info: PageInfo<BlockNumber>, bn_to_exclude_opt: Option<&BTreeSet<BlockNumber>>, amount_target_opt: Option<SourceAmount>, ) -> KvResult<PagedData<UdsWithSum>> { @@ -264,7 +264,7 @@ pub fn unspent_uds_of_pubkey<BcDb: BcV2DbReadable>( let mut blocks_numbers = if let Some(pos) = page_info.pos { if page_info.order { uds.iter( - UdIdV2(pubkey, BlockNumber(pos))..UdIdV2(pubkey, BlockNumber(u32::MAX)), + UdIdV2(pubkey, pos)..UdIdV2(pubkey, BlockNumber(u32::MAX)), |it| { let it = it.keys().map_ok(|UdIdV2(_p, bn)| bn); if let Some(bn_to_exclude) = bn_to_exclude_opt { @@ -276,18 +276,15 @@ pub fn unspent_uds_of_pubkey<BcDb: BcV2DbReadable>( }, )? } else { - uds.iter( - UdIdV2(pubkey, BlockNumber(0))..=UdIdV2(pubkey, BlockNumber(pos)), - |it| { - let it = it.keys().reverse().map_ok(|UdIdV2(_p, bn)| bn); - if let Some(bn_to_exclude) = bn_to_exclude_opt { - it.filter_ok(|bn| !bn_to_exclude.contains(&bn)) - .collect::<KvResult<Vec<_>>>() - } else { - it.collect::<KvResult<Vec<_>>>() - } - }, - )? + uds.iter(UdIdV2(pubkey, BlockNumber(0))..=UdIdV2(pubkey, pos), |it| { + let it = it.keys().reverse().map_ok(|UdIdV2(_p, bn)| bn); + if let Some(bn_to_exclude) = bn_to_exclude_opt { + it.filter_ok(|bn| !bn_to_exclude.contains(&bn)) + .collect::<KvResult<Vec<_>>>() + } else { + it.collect::<KvResult<Vec<_>>>() + } + })? } } else if page_info.order { uds.iter( @@ -354,14 +351,14 @@ pub fn unspent_uds_of_pubkey<BcDb: BcV2DbReadable>( }; Ok(PagedData { has_previous_page: has_previous_page( - uds_with_sum.uds.iter().map(|(bn, _sa)| bn.0), - first_ud_opt.map(|bn| bn.0), + uds_with_sum.uds.iter().map(|(bn, _sa)| bn), + first_ud_opt, page_info, true, ), has_next_page: has_next_page( - uds_with_sum.uds.iter().map(|(bn, _sa)| bn.0), - last_ud_opt.map(|bn| bn.0), + uds_with_sum.uds.iter().map(|(bn, _sa)| bn), + last_ud_opt, page_info, true, ), @@ -606,7 +603,7 @@ mod tests { &gva_db, pk, PageInfo { - pos: Some(50), + pos: Some(BlockNumber(50)), ..Default::default() }, )?; @@ -683,7 +680,7 @@ mod tests { &gva_db, pk, PageInfo { - pos: Some(55), + pos: Some(BlockNumber(55)), order: false, ..Default::default() }, @@ -750,7 +747,7 @@ mod tests { &bc_db, pk, PageInfo { - pos: Some(30), + pos: Some(BlockNumber(30)), ..Default::default() }, None, @@ -806,7 +803,7 @@ mod tests { &bc_db, pk, PageInfo { - pos: Some(40), + pos: Some(BlockNumber(40)), order: false, ..Default::default() }, diff --git a/rust-libs/duniter-dbs-read-ops/src/utxos.rs b/rust-libs/duniter-dbs-read-ops/src/utxos.rs index a27e0215d37439e53828e412361954bdef7b80de..45ba6e421339e25f7d34353d47c1d15ae1e4448b 100644 --- a/rust-libs/duniter-dbs-read-ops/src/utxos.rs +++ b/rust-libs/duniter-dbs-read-ops/src/utxos.rs @@ -18,17 +18,50 @@ use duniter_dbs::{GvaUtxoIdDbV1, SourceAmountValV2}; use crate::*; -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct UtxoIdWithBlockNumber(pub UtxoIdV10, pub BlockNumber); -impl std::fmt::Display for UtxoIdWithBlockNumber { +#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)] +pub struct UtxoCursor { + pub block_number: BlockNumber, + pub tx_hash: Hash, + pub output_index: u8, +} +impl std::fmt::Display for UtxoCursor { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}:{}:{}", self.1, self.0.tx_hash, self.0.output_index,) + write!( + f, + "{}:{}:{}", + self.block_number, self.tx_hash, self.output_index, + ) + } +} + +impl FromStr for UtxoCursor { + type Err = StringErr; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + let mut s = s.split(':'); + let block_number = s + .next() + .ok_or_else(wrong_cursor)? + .parse() + .map_err(|_| wrong_cursor())?; + let tx_hash = + Hash::from_hex(s.next().ok_or_else(wrong_cursor)?).map_err(|_| wrong_cursor())?; + let output_index = s + .next() + .ok_or_else(wrong_cursor)? + .parse() + .map_err(|_| wrong_cursor())?; + Ok(Self { + block_number, + tx_hash, + output_index, + }) } } #[derive(Debug, Default)] pub struct UtxosWithSum { - pub utxos: Vec<(UtxoIdWithBlockNumber, SourceAmount)>, + pub utxos: Vec<(UtxoCursor, SourceAmount)>, pub sum: SourceAmount, } @@ -36,7 +69,7 @@ pub fn find_script_utxos<GvaDb: GvaV1DbReadable, TxsMpDb: TxsMpV2DbReadable>( gva_db_ro: &GvaDb, txs_mp_db_ro: &TxsMpDb, amount_target_opt: Option<SourceAmount>, - page_info: PageInfo<String>, + page_info: PageInfo<UtxoCursor>, script: &WalletScriptV10, ) -> anyhow::Result<PagedData<UtxosWithSum>> { let mempool_filter = |k_res: KvResult<GvaUtxoIdDbV1>| match k_res { @@ -61,13 +94,10 @@ pub fn find_script_utxos<GvaDb: GvaV1DbReadable, TxsMpDb: TxsMpV2DbReadable>( .iter(k_min..k_max, |it| { it.keys().filter_map(mempool_filter).next_res() })? - .map(|gva_utxo_id| { - format!( - "{}:{}:{}", - gva_utxo_id.get_block_number(), - gva_utxo_id.get_tx_hash(), - gva_utxo_id.get_output_index() - ) + .map(|gva_utxo_id| UtxoCursor { + block_number: BlockNumber(gva_utxo_id.get_block_number()), + tx_hash: gva_utxo_id.get_tx_hash(), + output_index: gva_utxo_id.get_output_index(), }) } else { None @@ -78,35 +108,29 @@ pub fn find_script_utxos<GvaDb: GvaV1DbReadable, TxsMpDb: TxsMpV2DbReadable>( .iter(k_min..k_max, |it| { it.keys().reverse().filter_map(mempool_filter).next_res() })? - .map(|gva_utxo_id| { - format!( - "{}:{}:{}", - gva_utxo_id.get_block_number(), - gva_utxo_id.get_tx_hash(), - gva_utxo_id.get_output_index() - ) + .map(|gva_utxo_id| UtxoCursor { + block_number: BlockNumber(gva_utxo_id.get_block_number()), + tx_hash: gva_utxo_id.get_tx_hash(), + output_index: gva_utxo_id.get_output_index(), }) } else { None }; if let Some(ref pos) = page_info.pos { - let mut pos = pos.split(':'); - let block_number = pos - .next() - .ok_or_else(|| anyhow::Error::msg("invalid cursor"))? - .parse()?; - let tx_hash = Hash::from_hex( - pos.next() - .ok_or_else(|| anyhow::Error::msg("invalid cursor"))?, - )?; - let output_index = pos - .next() - .ok_or_else(|| anyhow::Error::msg("invalid cursor"))? - .parse()?; if page_info.order { - k_min = GvaUtxoIdDbV1::new_(script_hash, block_number, tx_hash, output_index); + k_min = GvaUtxoIdDbV1::new_( + script_hash, + pos.block_number.0, + pos.tx_hash, + pos.output_index, + ); } else { - k_max = GvaUtxoIdDbV1::new_(script_hash, block_number, tx_hash, output_index); + k_max = GvaUtxoIdDbV1::new_( + script_hash, + pos.block_number.0, + pos.tx_hash, + pos.output_index, + ); } } let mut sum = SourceAmount::ZERO; @@ -118,19 +142,17 @@ pub fn find_script_utxos<GvaDb: GvaV1DbReadable, TxsMpDb: TxsMpV2DbReadable>( let it = it.filter_map(|entry_res| match entry_res { Ok((gva_utxo_id, SourceAmountValV2(utxo_amount))) => { let tx_hash = gva_utxo_id.get_tx_hash(); - let output_index = gva_utxo_id.get_output_index() as u32; + let output_index = gva_utxo_id.get_output_index(); match txs_mp_db_ro .utxos_ids() - .contains_key(&UtxoIdDbV2(tx_hash, output_index)) + .contains_key(&UtxoIdDbV2(tx_hash, output_index as u32)) { Ok(false) => Some(Ok(( - UtxoIdWithBlockNumber( - UtxoIdV10 { - tx_hash, - output_index: output_index as usize, - }, - BlockNumber(gva_utxo_id.get_block_number()), - ), + UtxoCursor { + tx_hash, + output_index, + block_number: BlockNumber(gva_utxo_id.get_block_number()), + }, utxo_amount, ))), Ok(true) => None, @@ -218,17 +240,13 @@ pub fn find_script_utxos<GvaDb: GvaV1DbReadable, TxsMpDb: TxsMpV2DbReadable>( Ok(PagedData { has_next_page: has_next_page( - utxos - .iter() - .map(|(utxo_id_with_bn, _sa)| utxo_id_with_bn.to_string()), + utxos.iter().map(|(utxo_id_with_bn, _sa)| utxo_id_with_bn), last_cursor_opt, - page_info.clone(), + page_info, order, ), has_previous_page: has_previous_page( - utxos - .iter() - .map(|(utxo_id_with_bn, _sa)| utxo_id_with_bn.to_string()), + utxos.iter().map(|(utxo_id_with_bn, _sa)| utxo_id_with_bn), first_cursor_opt, page_info, order, @@ -281,7 +299,7 @@ mod tests { utxos, vec![ ( - UtxoIdWithBlockNumber( + UtxoCursor( UtxoIdV10 { tx_hash: Hash::default(), output_index: 0 @@ -291,7 +309,7 @@ mod tests { SourceAmount::with_base0(50) ), ( - UtxoIdWithBlockNumber( + UtxoCursor( UtxoIdV10 { tx_hash: Hash::default(), output_index: 1 @@ -324,7 +342,7 @@ mod tests { assert_eq!( utxos, vec![( - UtxoIdWithBlockNumber( + UtxoCursor( UtxoIdV10 { tx_hash: Hash::default(), output_index: 2 @@ -359,23 +377,19 @@ mod tests { utxos, vec![ ( - UtxoIdWithBlockNumber( - UtxoIdV10 { - tx_hash: Hash::default(), - output_index: 2 - }, - BlockNumber(0), - ), + UtxoCursor { + block_number: BlockNumber(0), + tx_hash: Hash::default(), + output_index: 2, + }, SourceAmount::with_base0(120) ), ( - UtxoIdWithBlockNumber( - UtxoIdV10 { - tx_hash: Hash::default(), - output_index: 1 - }, - BlockNumber(0), - ), + UtxoCursor { + block_number: BlockNumber(0), + tx_hash: Hash::default(), + output_index: 1, + }, SourceAmount::with_base0(80) ) ] diff --git a/rust-libs/modules/duniter-gva/src/lib.rs b/rust-libs/modules/duniter-gva/src/lib.rs index 82756eeed6119f7c28419798a4b634cc7802b738..025f23f8874cff4b6695834e933122908d4f8fc3 100644 --- a/rust-libs/modules/duniter-gva/src/lib.rs +++ b/rust-libs/modules/duniter-gva/src/lib.rs @@ -41,7 +41,7 @@ use crate::entities::{ }; use crate::inputs::{TxIssuer, TxRecipient, UdsFilter}; use crate::inputs_validators::TxCommentValidator; -use crate::pagination::{PaginationWithIntCursor, PaginationWithStrCursor}; +use crate::pagination::Pagination; use crate::schema::{GraphQlSchema, SchemaData}; #[cfg(test)] use crate::tests::create_dbs_reader; diff --git a/rust-libs/modules/duniter-gva/src/pagination.rs b/rust-libs/modules/duniter-gva/src/pagination.rs index 4f0bbe1feb8a22dfefa1e5fa455fb8771207e48e..c472d102d3f81f1d9d417c088408c423f2a69f6f 100644 --- a/rust-libs/modules/duniter-gva/src/pagination.rs +++ b/rust-libs/modules/duniter-gva/src/pagination.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + // Copyright (C) 2020 Éloïs SANCHEZ. // // This program is free software: you can redistribute it and/or modify @@ -27,34 +29,23 @@ impl Default for Order { } #[derive(Default, async_graphql::InputObject)] -pub(crate) struct PaginationWithStrCursor { +pub(crate) struct Pagination { /// Identifier of the 1st desired element (of the last one in descending order) cursor: Option<String>, ord: Order, page_size: Option<u32>, } -impl PaginationWithStrCursor { - pub(crate) fn convert_to_page_info(self) -> duniter_dbs_read_ops::PageInfo<String> { - duniter_dbs_read_ops::PageInfo::new( - self.cursor, - self.ord == Order::Asc, - self.page_size.map(|n| n as usize), - ) - } -} - -#[derive(Clone, Copy, Default, async_graphql::InputObject)] -pub(crate) struct PaginationWithIntCursor { - cursor: Option<u32>, - ord: Order, - page_size: Option<u32>, -} -impl PaginationWithIntCursor { - pub(crate) fn convert_to_page_info(self) -> duniter_dbs_read_ops::PageInfo<u32> { - duniter_dbs_read_ops::PageInfo::new( - self.cursor, +impl Pagination { + pub(crate) fn convert_to_page_info< + E: 'static + std::error::Error + Send + Sync, + T: FromStr<Err = E>, + >( + self, + ) -> anyhow::Result<duniter_dbs_read_ops::PageInfo<T>> { + Ok(duniter_dbs_read_ops::PageInfo::new( + self.cursor.map(|c| T::from_str(&c)).transpose()?, self.ord == Order::Asc, self.page_size.map(|n| n as usize), - ) + )) } } diff --git a/rust-libs/modules/duniter-gva/src/queries/uds.rs b/rust-libs/modules/duniter-gva/src/queries/uds.rs index a04fd2fb2c5ab8bf15d6a75a6c2d27ff4c82a486..3ec603ee392e88aec6ed88a78bcf766d4b41c821 100644 --- a/rust-libs/modules/duniter-gva/src/queries/uds.rs +++ b/rust-libs/modules/duniter-gva/src/queries/uds.rs @@ -46,10 +46,10 @@ impl UdsQuery { ctx: &async_graphql::Context<'_>, #[graphql(desc = "Ed25519 public key on base 58 representation")] pubkey: String, #[graphql(default)] filter: UdsFilter, - #[graphql(desc = "pagination", default)] pagination: PaginationWithIntCursor, + #[graphql(desc = "pagination", default)] pagination: Pagination, #[graphql(desc = "Amount needed")] amount: Option<i64>, ) -> async_graphql::Result<Connection<usize, UdGva, Sum, EmptyFields>> { - let pagination = PaginationWithIntCursor::convert_to_page_info(pagination); + let pagination = Pagination::convert_to_page_info(pagination)?; let pubkey = PublicKey::from_base58(&pubkey)?; diff --git a/rust-libs/modules/duniter-gva/src/queries/utxos.rs b/rust-libs/modules/duniter-gva/src/queries/utxos.rs index e184e1bd4392e0cebbc87bf230496fb1e992e6be..982d31f74481a42951ee468924e3a9479a725139 100644 --- a/rust-libs/modules/duniter-gva/src/queries/utxos.rs +++ b/rust-libs/modules/duniter-gva/src/queries/utxos.rs @@ -17,7 +17,7 @@ use crate::*; use async_graphql::connection::*; use duniter_dbs::GvaV1DbReadable; use duniter_dbs_read_ops::{ - utxos::{UtxoIdWithBlockNumber, UtxosWithSum}, + utxos::{UtxoCursor, UtxosWithSum}, PagedData, }; @@ -30,10 +30,10 @@ impl UtxosQuery { &self, ctx: &async_graphql::Context<'_>, #[graphql(desc = "DUBP wallet script")] script: String, - #[graphql(desc = "pagination", default)] pagination: PaginationWithStrCursor, + #[graphql(desc = "pagination", default)] pagination: Pagination, #[graphql(desc = "Amount needed")] amount: Option<i64>, ) -> async_graphql::Result<Connection<String, UtxoGva, Sum, EmptyFields>> { - let pagination = PaginationWithStrCursor::convert_to_page_info(pagination); + let pagination = Pagination::convert_to_page_info(pagination)?; let script = dubp::documents_parser::wallet_script_from_str(&script)?; @@ -61,11 +61,11 @@ impl UtxosQuery { &script, )?; let mut times = Vec::with_capacity(paged_data.data.utxos.len()); - for (UtxoIdWithBlockNumber(_utxo_id, bn), _sa) in &paged_data.data.utxos { + for (UtxoCursor { block_number, .. }, _sa) in &paged_data.data.utxos { times.push( dbs.gva_db .blockchain_time() - .get(&U32BE(bn.0))? + .get(&U32BE(block_number.0))? .unwrap_or_else(|| unreachable!()), ); } @@ -87,15 +87,15 @@ impl UtxosQuery { }, ); conn.append(utxos.into_iter().zip(times.into_iter()).map( - |((utxo_id_with_bn, source_amount), blockchain_time)| { + |((utxo_cursor, source_amount), blockchain_time)| { Edge::new( - utxo_id_with_bn.to_string(), + utxo_cursor.to_string(), UtxoGva { amount: source_amount.amount(), base: source_amount.base(), - tx_hash: utxo_id_with_bn.0.tx_hash.to_hex(), - output_index: utxo_id_with_bn.0.output_index as u32, - written_block: (utxo_id_with_bn.1).0, + tx_hash: utxo_cursor.tx_hash.to_hex(), + output_index: utxo_cursor.output_index as u32, + written_block: utxo_cursor.block_number.0, written_time: blockchain_time, }, )