Repository: MystenLabs/sui
File: crates/sui-indexer-alt/src/handlers/tx_balance_changes.rs (Rust)

Code before:
) -> Result<Vec<BalanceChange>> {
    // Shortcut if the transaction failed -- we know that only gas was charged.
    if transaction.effects.status().is_err() {
        let net_gas_usage = transaction.effects.gas_cost_summary().net_gas_usage();
        // This can happen if the transaction failed due to insufficient address balance.
        if net_gas_usage == 0 {
            return Ok(vec![]);
        }
        return Ok(vec![BalanceChange::V1 {
            owner: transaction.effects.gas_object().1,
            coin_type: GAS::type_tag().to_canonical_string(/* with_prefix */ true),
            amount: -(net_gas_usage as i128),
        }]);
    }

    // First gather address balance changes from accumulator events.
    let mut balance_changes = address_balance_changes_from_accumulator_events(&transaction.effects)
        .fold(
            BTreeMap::<(Owner, TypeTag), i128>::new(),
            |mut acc, (addr, coin_type, amt)| {
                // We always transfer address balance funds to an address.
                *acc.entry((Owner::AddressOwner(addr), coin_type))
                    .or_default() += amt;
                acc
            },
        );

    // Then gather coin balance changes from input and output objects.
    for object in transaction.input_objects(&checkpoint.object_set) {
        if let Some((type_, balance)) = Coin::extract_balance_if_coin(object)? {
            *balance_changes
                .entry((object.owner().clone(), type_))
                .or_insert(0i128) -= balance as i128;
        }
    }

    for object in transaction.output_objects(&checkpoint.object_set) {
        if let Some((type_, balance)) = Coin::extract_balance_if_coin(object)? {
            *balance_changes
                .entry((object.owner().clone(), type_))
                .or_insert(0i128) += balance as i128;
        }
    }

    Ok(balance_changes
        .into_iter()
        .filter_map(|((owner, coin_type), amount)| {
            if amount == 0 {
                None
            } else {
                Some(BalanceChange::V1 {

Review comment (suggestion):
This is more in keeping with how the existing implementation worked.

```suggestion
    let mut changes = BTreeMap::new();
    
    for (addr, type_, balance) in address_balance_changes_from_accumulator_events(&transaction.effects) {
        *changes
            .entry((Owner::AddressOwner(addr), type_))
            .or_insert(0i128) += balance;
    }
```

Code after:
) -> Result<Vec<BalanceChange>> {
    // Shortcut if the transaction failed -- we know that only gas was charged.
    if transaction.effects.status().is_err() {
        let net_gas_usage = transaction.effects.gas_cost_summary().net_gas_usage();
        return Ok(Vec::from_iter((net_gas_usage > 0).then(|| {
            BalanceChange::V1 {
                owner: transaction.effects.gas_object().1,
                coin_type: GAS::type_tag().to_canonical_string(true),
                amount: -(net_gas_usage as i128),
            }
        })));
    }

    let mut changes = BTreeMap::new();

    // First gather address balance changes from accumulator events.
    for (addr, type_, balance) in
        address_balance_changes_from_accumulator_events(&transaction.effects)
    {
        *changes
            .entry((Owner::AddressOwner(addr), type_))
            .or_insert(0i128) += balance;
    }

    // Then gather coin balance changes from input and output objects.
    for object in transaction.input_objects(&checkpoint.object_set) {
        if let Some((type_, balance)) = Coin::extract_balance_if_coin(object)? {
            *changes
                .entry((object.owner().clone(), type_))
                .or_insert(0i128) -= balance as i128;
        }
    }

    for object in transaction.output_objects(&checkpoint.object_set) {
        if let Some((type_, balance)) = Coin::extract_balance_if_coin(object)? {
            *changes
                .entry((object.owner().clone(), type_))
                .or_insert(0i128) += balance as i128;
        }
    }

    Ok(changes
        .into_iter()
        .filter_map(|((owner, coin_type), amount)| {
            (amount != 0).then(|| BalanceChange::V1 {
                owner,
                coin_type: coin_type.to_canonical_string(/* with_prefix */ true),
                amount,
            })
        })
        .collect())