Skip to content

Commit

Permalink
Fix: Latest balances fix (RA-97)
Browse files Browse the repository at this point in the history
* Fix: Took balances from the latest block in case of multiple occurrences.
* Fix: reduce validations assuming the YACI store will store validated data
  • Loading branch information
BerezinD committed May 7, 2024
1 parent 3c42579 commit cf30a02
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@ public interface AddressBalanceRepository extends
// "WHERE b.address = :address AND b.blockNumber <= :number " +
// "GROUP BY b.address, b.unit, b.quantity, b.addrFull, b.policy, b.assetName, b.paymentCredential, b.stakeAddress, b.blockHash, b.epoch")
@Query(value =
"SELECT b from AddressBalanceEntity b WHERE b.blockNumber in (SELECT MAX(c.blockNumber) FROM AddressBalanceEntity c WHERE c.address = :address AND c.blockNumber <= :number GROUP BY c.unit) AND b.address = :address")
"""
SELECT b FROM AddressBalanceEntity b
WHERE (b.blockNumber, b.unit) in
(SELECT MAX(c.blockNumber), c.unit FROM AddressBalanceEntity c
WHERE c.address = :address AND c.blockNumber <= :number
GROUP BY c.unit)
AND b.address = :address
""")
List<AddressBalanceEntity> findAddressBalanceByAddressAndBlockNumber(
@Param("address") String address, @Param("number") Long number);
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,26 +148,38 @@ public static Amount mapAmount(String value, String symbol, Integer decimals,

/**
* Maps a list of AddressBalanceDTOs to a Rosetta compatible AccountBalanceResponse.
*
* @param block The block from where the balances are calculated into the past
* @param balances The balances of the addresses
* @param balances The list of filtered balances up to {@code block} number.
* Each unit should occur only one time with the latest balance.
* Native assets should be present only as a lovelace unit.
* @return The Rosetta compatible AccountBalanceResponse
*/
public static AccountBalanceResponse mapToAccountBalanceResponse(Block block, List<AddressBalance> balances) {
List<AddressBalance> nonLovelaceBalances = balances.stream().filter(balance -> !balance.unit().equals(Constants.LOVELACE) && !balance.unit().equals(Constants.ADA)).toList();
long sum = balances.stream().filter(balance -> balance.unit().equals(Constants.LOVELACE) || balance.unit().equals(Constants.ADA)).mapToLong(value -> value.quantity().longValue()).sum();
BigInteger lovelaceAmount = balances.stream()
.filter(b -> Constants.LOVELACE.equals(b.unit()))
.map(AddressBalance::quantity)
.findFirst()
.orElse(BigInteger.ZERO);
List<Amount> amounts = new ArrayList<>();
if (sum > 0) {
amounts.add(mapAmount(String.valueOf(sum)));
if (lovelaceAmount.compareTo(BigInteger.ZERO) > 0) {
amounts.add(mapAmount(String.valueOf(lovelaceAmount)));
}
nonLovelaceBalances.forEach(balance -> amounts.add(mapAmount(balance.quantity().toString(), balance.unit().substring(Constants.POLICY_ID_LENGTH), Constants.MULTI_ASSET_DECIMALS, new CurrencyMetadata(
balance.unit().substring(0, Constants.POLICY_ID_LENGTH)))));
balances.stream()
.filter(b -> !Constants.LOVELACE.equals(b.unit()))
.forEach(b -> amounts.add(
mapAmount(b.quantity().toString(),
b.unit().substring(Constants.POLICY_ID_LENGTH),
Constants.MULTI_ASSET_DECIMALS,
new CurrencyMetadata(b.unit().substring(0, Constants.POLICY_ID_LENGTH)))
));
return AccountBalanceResponse.builder()
.blockIdentifier(BlockIdentifier.builder()
.hash(block.getHash())
.index(block.getNumber())
.build())
.balances(amounts)
.build();
.blockIdentifier(BlockIdentifier.builder()
.hash(block.getHash())
.index(block.getNumber())
.build())
.balances(amounts)
.build();
}

public static AccountBalanceResponse mapToStakeAddressBalanceResponse(Block block, StakeAddressBalance balance) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ void getAccountBalanceNoStakeAddressPositiveTest() {
AccountIdentifier accountIdentifier = getMockedAccountIdentifierAndMockAccountBalanceRequest(
accountBalanceRequest, blockIdentifier, accountAddress);
Block block = getMockBlock();
AddressBalance addressBalance = new AddressBalance(accountAddress, ADA, 1L,
AddressBalance addressBalance = new AddressBalance(accountAddress, LOVELACE, 1L,
BigInteger.valueOf(1000L), 1L);
when(ledgerBlockService.findBlock(1L, HASH)).thenReturn(block);
when(ledgerDataProviderService.findBalanceByAddressAndBlock(accountAddress, 1L))
Expand All @@ -74,6 +74,8 @@ void getAccountBalanceNoStakeAddressPositiveTest() {
assertNotNull(actual);
assertEquals("1000", actual.getBalances().getFirst().getValue());
assertNotNull(actual.getBalances().getFirst().getCurrency().getSymbol());
assertEquals(Constants.ADA, actual.getBalances().getFirst().getCurrency().getSymbol());
assertEquals(Constants.ADA_DECIMALS, actual.getBalances().getFirst().getCurrency().getDecimals());
assertEquals(blockIdentifier.getIndex(), actual.getBlockIdentifier().getIndex());
assertEquals(blockIdentifier.getHash(), actual.getBlockIdentifier().getHash());
verify(ledgerBlockService).findBlock(1L, HASH);
Expand Down Expand Up @@ -124,7 +126,7 @@ void getAccountBalanceNoStakeAddressNullBlockIdentifierPositiveTest() {
when(accountBalanceRequest.getAccountIdentifier()).thenReturn(accountIdentifier);
when(accountIdentifier.getAddress()).thenReturn(accountAddress);
Block block = getMockBlock();
AddressBalance addressBalance = new AddressBalance(accountAddress, ADA, 1L,
AddressBalance addressBalance = new AddressBalance(accountAddress, LOVELACE, 1L,
BigInteger.valueOf(1000L), 1L);
when(ledgerBlockService.findLatestBlock()).thenReturn(block);
when(ledgerDataProviderService.findBalanceByAddressAndBlock(accountAddress, 1L))
Expand All @@ -135,6 +137,8 @@ void getAccountBalanceNoStakeAddressNullBlockIdentifierPositiveTest() {
assertNotNull(actual);
assertEquals("1000", actual.getBalances().getFirst().getValue());
assertNotNull(actual.getBalances().getFirst().getCurrency().getSymbol());
assertEquals(Constants.ADA, actual.getBalances().getFirst().getCurrency().getSymbol());
assertEquals(Constants.ADA_DECIMALS, actual.getBalances().getFirst().getCurrency().getDecimals());
assertEquals(block.getNumber(), actual.getBlockIdentifier().getIndex());
assertEquals(block.getHash(), actual.getBlockIdentifier().getHash());
verify(ledgerBlockService).findLatestBlock();
Expand Down

0 comments on commit cf30a02

Please sign in to comment.