Skip to main content

sui_indexer_alt_reader/
tx_balance_changes.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use 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/// Key for fetching a transaction's balance changes by digest.
21#[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}