Skip to content

Commit

Permalink
Merge pull request #1188 from cardano-foundation/feature/update-addre…
Browse files Browse the repository at this point in the history
…s-controller-when-migrate-with-new-ls-schema

chore: update address controller when migrate with new ls schema
  • Loading branch information
Sotatek-DucPhung committed May 7, 2024
2 parents 78af01b + 5ee08e0 commit e480d3c
Show file tree
Hide file tree
Showing 14 changed files with 874 additions and 612 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
package org.cardanofoundation.explorer.api.controller;

import jakarta.validation.Valid;

import lombok.RequiredArgsConstructor;

import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;

import org.cardanofoundation.explorer.api.common.enumeration.AnalyticType;
import org.cardanofoundation.explorer.api.config.LogMessage;
import org.cardanofoundation.explorer.api.model.response.BaseFilterResponse;
import org.cardanofoundation.explorer.api.model.response.address.AddressChartBalanceResponse;
import org.cardanofoundation.explorer.api.model.response.address.AddressFilterResponse;
import org.cardanofoundation.explorer.api.model.response.address.AddressResponse;
import org.cardanofoundation.explorer.api.model.response.token.TokenAddressResponse;
import org.cardanofoundation.explorer.api.service.AddressService;
import org.cardanofoundation.explorer.api.service.TxService;
import org.cardanofoundation.explorer.common.entity.ledgersync.LatestTokenBalance_;
import org.cardanofoundation.explorer.common.validation.pagination.PageZeroValid;
import org.cardanofoundation.explorer.common.validation.pagination.Pagination;
import org.cardanofoundation.explorer.common.validation.pagination.PaginationDefault;
import org.cardanofoundation.explorer.common.validation.pagination.PaginationValid;
import org.springdoc.core.annotations.ParameterObject;

@RestController
@RequestMapping("/api/v1/addresses")
Expand All @@ -21,50 +40,54 @@ public class AddressController {

private final TxService txService;

// @GetMapping("/{address}")
// @LogMessage
// @Operation(
// summary = "Get detail information of payment address",
// description =
// "Get detail information of payment address with balance, txs, token and check
// contract",
// tags = {"address"})
// public ResponseEntity<AddressResponse> getAddressDetail(
// @PathVariable
// @Parameter(
// description =
// "The human readable encoding of the output address."
// + " Will be Base58 for Byron era addresses and Bech32 for Shelley era.")
// String address) {
// return ResponseEntity.ok(addressService.getAddressDetail(address));
// }
@GetMapping("/{address}")
@LogMessage
@Operation(
summary = "Get detail information of payment address",
description =
"Get detail information of payment address with balance, txs, token and check contract",
tags = {"address"})
public ResponseEntity<AddressResponse> getAddressDetail(
@PathVariable
@Parameter(
description =
"The human readable encoding of the output address."
+ " Will be Base58 for Byron era addresses and Bech32 for Shelley era.")
String address) {
return ResponseEntity.ok(addressService.getAddressDetail(address));
}

// @GetMapping("/top-addresses")
// @LogMessage
// @Operation(
// summary = "Get top address by balance",
// tags = {"address"})
// public ResponseEntity<BaseFilterResponse<AddressFilterResponse>> getTopAddress(
// @ParameterObject @PaginationValid @PageZeroValid @Valid Pagination pagination) {
// return ResponseEntity.ok(addressService.getTopAddress(pagination.toPageable()));
// }
@GetMapping("/top-addresses")
@LogMessage
@Operation(
summary = "Get top address by balance",
tags = {"address"})
public ResponseEntity<BaseFilterResponse<AddressFilterResponse>> getTopAddress(
@ParameterObject
@PaginationDefault(
size = 20,
sort = {LatestTokenBalance_.QUANTITY},
direction = Sort.Direction.DESC)
@PaginationValid @PageZeroValid @Valid Pagination pagination) {
return ResponseEntity.ok(addressService.getTopAddress(pagination.toPageable()));
}

// @GetMapping("/analytics/{address}/{type}")
// @LogMessage
// @Operation(
// summary = "Get analytics of address",
// description = "Get analytics balance of address and time type",
// tags = {"address"})
// public ResponseEntity<AddressChartBalanceResponse> getAddressAnalytics(
// @PathVariable
// @Parameter(
// description =
// "The human readable encoding of the output address."
// + " Will be Base58 for Byron era addresses and Bech32 for Shelley era.")
// String address,
// @PathVariable @Parameter(description = "Type for analytics by time") AnalyticType type) {
// return ResponseEntity.ok(addressService.getAddressAnalytics(address, type));
// }
@GetMapping("/analytics/{address}/{type}")
@LogMessage
@Operation(
summary = "Get analytics of address",
description = "Get analytics balance of address and time type",
tags = {"address"})
public ResponseEntity<AddressChartBalanceResponse> getAddressAnalytics(
@PathVariable
@Parameter(
description =
"The human readable encoding of the output address."
+ " Will be Base58 for Byron era addresses and Bech32 for Shelley era.")
String address,
@PathVariable @Parameter(description = "Type for analytics by time") AnalyticType type) {
return ResponseEntity.ok(addressService.getAddressAnalytics(address, type));
}

// @GetMapping("/{address}/txs")
// @LogMessage
Expand All @@ -83,25 +106,24 @@ public class AddressController {
// pagination.toPageable()));
// }

// @GetMapping("/{address}/tokens")
// @LogMessage
// @Operation(
// summary = "Get list token by address",
// description =
// "Get list token by address with search by display name, will return all token if
// display name is null or empty",
// tags = {"address"})
// public ResponseEntity<BaseFilterResponse<TokenAddressResponse>> getTokenByAddress(
// @PathVariable
// @Parameter(
// description =
// "The human readable encoding of the output address."
// + " Will be Base58 for Byron era addresses and Bech32 for Shelley era.")
// String address,
// @RequestParam(required = false) @Parameter(description = "Display name query for search")
// String displayName,
// @ParameterObject @PaginationValid @Valid Pagination pagination) {
// return ResponseEntity.ok(
// addressService.getTokenByDisplayName(pagination.toPageable(), address, displayName));
// }
@GetMapping("/{address}/tokens")
@LogMessage
@Operation(
summary = "Get list token by address",
description =
"Get list token by address with search by display name, will return all token if display name is null or empty",
tags = {"address"})
public ResponseEntity<BaseFilterResponse<TokenAddressResponse>> getTokenByAddress(
@PathVariable
@Parameter(
description =
"The human readable encoding of the output address."
+ " Will be Base58 for Byron era addresses and Bech32 for Shelley era.")
String address,
@RequestParam(required = false) @Parameter(description = "Display name query for search")
String displayName,
@ParameterObject @PaginationValid @Valid Pagination pagination) {
return ResponseEntity.ok(
addressService.getTokenByDisplayName(pagination.toPageable(), address, displayName));
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
package org.cardanofoundation.explorer.api.mapper;

import org.cardanofoundation.explorer.api.model.response.address.AddressResponse;
import org.mapstruct.Mapper;

import org.cardanofoundation.explorer.api.model.response.address.AddressFilterResponse;
import org.cardanofoundation.explorer.api.model.response.contract.ContractFilterResponse;
import org.cardanofoundation.explorer.common.entity.ledgersync.Address;
import org.mapstruct.Mapping;

@Mapper(componentModel = "spring")
public interface AddressMapper {

ContractFilterResponse fromAddressToContractFilter(Address address);

// @Mapping(target = "stakeAddress", source = "stakeAddress.view")
// AddressResponse fromAddress(Address address);
AddressResponse fromAddress(Address address);

AddressFilterResponse fromAddressToFilterResponse(Address address);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,10 @@ public class AddressResponse {
private String scriptHash;
private boolean isAssociatedSmartContract;
private boolean isAssociatedNativeScript;

public AddressResponse(String address, Long txCount, BigInteger balance) {
this.address = address;
this.txCount = txCount;
this.balance = balance;
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
package org.cardanofoundation.explorer.api.repository.ledgersync;

import java.util.List;
import java.util.Optional;

import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.EntityGraph;
import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import org.cardanofoundation.explorer.api.model.response.address.AddressFilterResponse;
import org.cardanofoundation.explorer.api.model.response.address.AddressResponse;
import org.cardanofoundation.explorer.common.entity.ledgersync.Address;
import org.cardanofoundation.explorer.common.entity.ledgersync.AddressTxAmount;
import org.cardanofoundation.explorer.common.entity.ledgersync.AddressTxCount;

public interface AddressRepository extends JpaRepository<Address, Long> {

Expand All @@ -15,8 +24,7 @@ public interface AddressRepository extends JpaRepository<Address, Long> {
// @Query("SELECT address FROM Address address" + " ORDER BY address.balance DESC")
// List<Address> findAllOrderByBalance(Pageable pageable);

// @EntityGraph(attributePaths = {Address_.STAKE_ADDRESS})
// Optional<Address> findFirstByAddress(@Param("address") String address);
Optional<Address> findFirstByAddress(@Param("address") String address);

// @Query("SELECT addr FROM Address addr WHERE addr.stakeAddress.view = :stakeAddress")
// Page<Address> findByStakeAddress(@Param("stakeAddress") String stakeAddress, Pageable
Expand All @@ -26,4 +34,15 @@ public interface AddressRepository extends JpaRepository<Address, Long> {
//
@Query(value = "SELECT addr.address FROM Address addr WHERE addr.paymentCredential = :scriptHash")
List<String> getAssociatedAddress(@Param("scriptHash") String scriptHash);

@Query(value =
"""
SELECT new org.cardanofoundation.explorer.api.model.response.address.AddressResponse
(addr.address, CAST(COALESCE(addrTxCount.txCount, 0) AS long), CAST(COALESCE(latestAddrBalance.quantity, 0) AS biginteger))
FROM Address addr
LEFT JOIN AddressTxCount addrTxCount ON addr.address = addrTxCount.address
LEFT JOIN LatestAddressBalance latestAddrBalance ON addr.address = latestAddrBalance.address
WHERE addr.address = :address
""")
AddressResponse getAddressDetail(@Param("address") String address);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.cardanofoundation.explorer.api.repository.ledgersync;


import java.math.BigInteger;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import org.cardanofoundation.explorer.api.projection.MinMaxProjection;
import org.cardanofoundation.explorer.common.entity.compositeKey.AddressTxAmountId;
import org.cardanofoundation.explorer.common.entity.ledgersync.AddressTxAmount;

public interface AddressTxAmountRepository
extends JpaRepository<AddressTxAmount, AddressTxAmountId> {

@Query(
value =
"""
select :fromBalance + coalesce(min(calculated_balances.sum_balance), 0) as minVal,
:fromBalance + coalesce(max(calculated_balances.sum_balance), 0) as maxVal
from (select sum(ata.quantity) over (order by ata.slot rows unbounded PRECEDING) as sum_balance
from address_tx_amount ata
where ata.address = :address
and ata.unit = 'lovelace'
and ata.block_time > :fromDate
and ata.block_time <= :toDate) as calculated_balances
""", nativeQuery = true)
MinMaxProjection findMinMaxBalanceByAddress(
@Param("address") String address,
@Param("fromBalance") BigInteger fromBalance,
@Param("fromDate") Long fromDate,
@Param("toDate") Long toDate);


@Query(
"SELECT sum(addressTxBalance.quantity) FROM AddressTxAmount addressTxBalance"
+ " WHERE addressTxBalance.address = :address"
+ " AND addressTxBalance.blockTime > :from and addressTxBalance.blockTime <= :to")
Optional<BigInteger> getBalanceByAddressAndTime(@Param("address") String address,
@Param("from") Long from,
@Param("to") Long to);


@Query(
value =
"""
SELECT sum(ata.quantity)
FROM AddressTxAmount ata
WHERE ata.address = :address
AND ata.unit = 'lovelace'
AND ata.blockTime <= :to
""")
Optional<BigInteger> sumBalanceByAddress(
@Param("address") String address, @Param("to") Long to);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.cardanofoundation.explorer.api.repository.ledgersync;

import java.util.Collection;
import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

import org.cardanofoundation.explorer.common.entity.ledgersync.AddressTxCount;

public interface AddressTxCountRepository extends JpaRepository<AddressTxCount, String> {

List<AddressTxCount> findAllByAddressIn(Collection<String> addressList);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@
import org.springframework.data.repository.query.Param;

import org.cardanofoundation.explorer.api.projection.AggregateAddressBalanceProjection;
import org.cardanofoundation.explorer.common.entity.compositeKey.AggAddressTxBalanceId;
import org.cardanofoundation.explorer.common.entity.ledgersync.aggregation.AggregateAddressTxBalance;

public interface AggregateAddressTxBalanceRepository
extends JpaRepository<AggregateAddressTxBalance, Long> {
extends JpaRepository<AggregateAddressTxBalance, AggAddressTxBalanceId> {

@Query(
value =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.cardanofoundation.explorer.api.repository.ledgersync;


import org.springframework.data.jpa.repository.JpaRepository;

import org.cardanofoundation.explorer.common.entity.compositeKey.AddressBalanceId;
import org.cardanofoundation.explorer.common.entity.ledgersync.LatestAddressBalance;

public interface LatestAddressBalanceRepository extends JpaRepository<LatestAddressBalance, AddressBalanceId>{
}

0 comments on commit e480d3c

Please sign in to comment.