sui_indexer_alt_reader/
tx_balance_changes.rs1use std::collections::BTreeSet;
5use std::collections::HashMap;
6
7use async_graphql::dataloader::Loader;
8use diesel::ExpressionMethods;
9use diesel::JoinOnDsl;
10use diesel::QueryDsl;
11use diesel::SelectableHelper;
12use sui_indexer_alt_schema::schema::tx_balance_changes;
13use sui_indexer_alt_schema::schema::tx_digests;
14use sui_indexer_alt_schema::transactions::StoredTxBalanceChange;
15use sui_types::digests::TransactionDigest;
16
17use crate::error::Error;
18use crate::pg_reader::PgReader;
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22pub struct TxBalanceChangeKey(pub TransactionDigest);
23
24#[async_trait::async_trait]
25impl Loader<TxBalanceChangeKey> for PgReader {
26 type Value = StoredTxBalanceChange;
27 type Error = Error;
28
29 async fn load(
30 &self,
31 keys: &[TxBalanceChangeKey],
32 ) -> Result<HashMap<TxBalanceChangeKey, Self::Value>, Error> {
33 use tx_balance_changes::dsl as b;
34 use tx_digests::dsl as t;
35
36 if keys.is_empty() {
37 return Ok(HashMap::new());
38 }
39
40 let mut conn = self.connect().await?;
41
42 let digests: BTreeSet<_> = keys.iter().map(|d| d.0.into_inner()).collect();
43 let balance_changes: Vec<(Vec<u8>, StoredTxBalanceChange)> = conn
44 .results(
45 b::tx_balance_changes
46 .inner_join(t::tx_digests.on(b::tx_sequence_number.eq(t::tx_sequence_number)))
47 .select((t::tx_digest, StoredTxBalanceChange::as_select()))
48 .filter(t::tx_digest.eq_any(digests)),
49 )
50 .await?;
51
52 let digest_to_balance_changes: HashMap<_, _> = balance_changes.into_iter().collect();
53
54 Ok(keys
55 .iter()
56 .filter_map(|key| {
57 let slice: &[u8] = key.0.as_ref();
58 Some((*key, digest_to_balance_changes.get(slice).cloned()?))
59 })
60 .collect())
61 }
62}