Skip to content

Commit

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

chore: update token controller when migrate with new ls schema
  • Loading branch information
Sotatek-DucPhung committed May 8, 2024
2 parents e480d3c + 52508da commit 8607142
Show file tree
Hide file tree
Showing 10 changed files with 824 additions and 772 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.cardanofoundation.explorer.api.controller;

import java.util.List;
import java.util.concurrent.ExecutionException;

import jakarta.validation.Valid;
Expand All @@ -14,6 +15,8 @@
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.common.entity.ledgersync.LatestTokenBalance_;
import org.springdoc.core.annotations.ParameterObject;

import org.cardanofoundation.explorer.api.common.constant.CommonConstant;
Expand Down Expand Up @@ -48,17 +51,17 @@ public ResponseEntity<BaseFilterResponse<TokenFilterResponse>> filter(
return ResponseEntity.ok(tokenService.filterToken(query, pagination.toPageable()));
}

// @GetMapping("/{tokenId}")
// @LogMessage
// @Operation(summary = "Detail token")
// public ResponseEntity<TokenResponse> getTokenDetail(
// @PathVariable
// @PrefixedValid(CommonConstant.PREFIXED_TOKEN_FINGERPRINT)
// @LengthValid(CommonConstant.TOKEN_FINGERPRINT_LENGTH)
// @Parameter(description = "The CIP14 fingerprint for the MultiAsset.")
// String tokenId) {
// return ResponseEntity.ok(tokenService.getTokenDetail(tokenId));
// }
@GetMapping("/{tokenId}")
@LogMessage
@Operation(summary = "Detail token")
public ResponseEntity<TokenResponse> getTokenDetail(
@PathVariable
@PrefixedValid(CommonConstant.PREFIXED_TOKEN_FINGERPRINT)
@LengthValid(CommonConstant.TOKEN_FINGERPRINT_LENGTH)
@Parameter(description = "The CIP14 fingerprint for the MultiAsset.")
String tokenId) {
return ResponseEntity.ok(tokenService.getTokenDetail(tokenId));
}

@GetMapping("/{tokenId}/mints")
@LogMessage
Expand All @@ -78,18 +81,24 @@ public ResponseEntity<BaseFilterResponse<TokenMintTxResponse>> getTokenMintTx(
return ResponseEntity.ok(tokenService.getMintTxs(tokenId, pagination.toPageable()));
}

// @GetMapping("/{tokenId}/top_holders")
// @LogMessage
// @Operation(summary = "Filter holders by token")
// public ResponseEntity<BaseFilterResponse<TokenAddressResponse>> getTopHolders(
// @PathVariable
// @PrefixedValid(CommonConstant.PREFIXED_TOKEN_FINGERPRINT)
// @LengthValid(CommonConstant.TOKEN_FINGERPRINT_LENGTH)
// @Parameter(description = "The CIP14 fingerprint for the MultiAsset.")
// String tokenId,
// @ParameterObject @PaginationValid @Valid Pagination pagination) {
// return ResponseEntity.ok(tokenService.getTopHolders(tokenId, pagination.toPageable()));
// }
@GetMapping("/{tokenId}/top_holders")
@LogMessage
@Operation(summary = "Filter holders by token")
public ResponseEntity<BaseFilterResponse<TokenAddressResponse>> getTopHolders(
@PathVariable
@PrefixedValid(CommonConstant.PREFIXED_TOKEN_FINGERPRINT)
@LengthValid(CommonConstant.TOKEN_FINGERPRINT_LENGTH)
@Parameter(description = "The CIP14 fingerprint for the MultiAsset.")
String tokenId,
@ParameterObject
@PaginationValid
@PaginationDefault(
sort = {LatestTokenBalance_.QUANTITY},
direction = Sort.Direction.DESC)
@Valid
Pagination pagination) {
return ResponseEntity.ok(tokenService.getTopHolders(tokenId, pagination.toPageable()));
}

// @GetMapping("/{tokenId}/txs")
// @LogMessage
Expand All @@ -105,16 +114,16 @@ public ResponseEntity<BaseFilterResponse<TokenMintTxResponse>> getTokenMintTx(
// pagination.toPageable()));
// }

// @GetMapping("/analytics/{tokenId}/{type}")
// @LogMessage
// @Operation(summary = "Filter transaction by token")
// public ResponseEntity<List<TokenVolumeAnalyticsResponse>> getTokenVolumeAnalytics(
// @PathVariable
// @PrefixedValid(CommonConstant.PREFIXED_TOKEN_FINGERPRINT)
// @LengthValid(CommonConstant.TOKEN_FINGERPRINT_LENGTH)
// @Parameter(description = "The CIP14 fingerprint for the MultiAsset.")
// String tokenId,
// @PathVariable @Parameter(description = "Type analytics") AnalyticType type) {
// return ResponseEntity.ok(tokenService.getTokenVolumeAnalytic(tokenId, type));
// }
@GetMapping("/analytics/{tokenId}/{type}")
@LogMessage
@Operation(summary = "Filter transaction by token")
public ResponseEntity<List<TokenVolumeAnalyticsResponse>> getTokenVolumeAnalytics(
@PathVariable
@PrefixedValid(CommonConstant.PREFIXED_TOKEN_FINGERPRINT)
@LengthValid(CommonConstant.TOKEN_FINGERPRINT_LENGTH)
@Parameter(description = "The CIP14 fingerprint for the MultiAsset.")
String tokenId,
@PathVariable @Parameter(description = "Type analytics") AnalyticType type) {
return ResponseEntity.ok(tokenService.getTokenVolumeAnalytic(tokenId, type));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

import org.springframework.beans.factory.annotation.Value;

import com.bloxbean.cardano.client.address.util.AddressUtil;
import org.apache.commons.lang3.StringUtils;
import org.cardanofoundation.explorer.api.common.enumeration.AddressType;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
Expand Down Expand Up @@ -45,6 +47,7 @@ public abstract class TokenMapper {
expression = "java(HexUtils.fromHex(projection.getTokenName(), projection.getFingerprint()))")
@Mapping(target = "name", source = "tokenName")
@Mapping(target = "metadata", expression = "java(getMetadata(projection))")
@Mapping(target = "addressType", expression = "java(getAddressType(projection.getAddress()))")
public abstract TokenAddressResponse fromAddressTokenProjection(
AddressTokenProjection projection);

Expand Down Expand Up @@ -74,6 +77,10 @@ String getTokenLogoEndpoint(String logo) {
return Objects.isNull(logo) ? null : (tokenLogoEndpoint + logo);
}

AddressType getAddressType(String address) {
return address.startsWith("stake") ? AddressType.STAKE_ADDRESS : AddressType.PAYMENT_ADDRESS;
}

TokenMetadataResponse getMetadata(AddressTokenProjection projection) {
if (StringUtils.isEmpty(projection.getSubject())) {
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.cardanofoundation.explorer.api.repository.ledgersync;

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

Expand Down Expand Up @@ -30,10 +31,10 @@ public interface AddressRepository extends JpaRepository<Address, Long> {
// Page<Address> findByStakeAddress(@Param("stakeAddress") String stakeAddress, Pageable
// pageable);
//
// List<Address> findAddressByIdIn(@Param("idList") Collection<Long> idList);
//
@Query(value = "SELECT addr.address FROM Address addr WHERE addr.paymentCredential = :scriptHash")
List<String> getAssociatedAddress(@Param("scriptHash") String scriptHash);
List<Address> findAddressByIdIn(@Param("idList") Collection<Long> idList);

@Query(value = "SELECT addr.address FROM Address addr WHERE addr.paymentCredential = :scriptHash")
List<String> getAssociatedAddress(@Param("scriptHash") String scriptHash);

@Query(value =
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ Optional<BigInteger> getBalanceByAddressAndTime(@Param("address") String address
@Param("from") Long from,
@Param("to") Long to);


@Query(
value =
"""
Expand All @@ -56,4 +55,18 @@ SELECT sum(ata.quantity)
""")
Optional<BigInteger> sumBalanceByAddress(
@Param("address") String address, @Param("to") Long to);

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

import org.springframework.data.domain.Page;

import java.sql.Timestamp;
import java.util.List;

import org.springframework.data.domain.Pageable;
Expand Down Expand Up @@ -62,4 +64,21 @@ Page<AddressTokenProjection> findTokenAndBalanceByAddressAndNameView(
""")
List<AddressTokenProjection> findAddressAndBalanceByPolicy(
@Param("policy") String policy, Pageable pageable);

@Query(value =
"""
SELECT max(ltb.block_time)
FROM latest_token_balance ltb
WHERE ltb.unit = :unit
""", nativeQuery = true)
Long getLastActivityTimeOfToken(@Param("unit") String unit);

@Query(value =
"""
select (case when ltb.stakeAddress is null then ltb.address else ltb.stakeAddress end) as address, ltb.quantity as quantity
from LatestTokenBalance ltb
where ltb.unit = :unit
and ltb.quantity > 0
""")
List<AddressTokenProjection> getTopHolderOfToken(@Param("unit") String unit, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.cardanofoundation.explorer.api.repository.ledgersync;

import java.sql.Timestamp;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.cardanofoundation.explorer.api.service;

import java.util.List;
import java.util.concurrent.ExecutionException;

import org.springframework.data.domain.Pageable;

import org.cardanofoundation.explorer.api.common.enumeration.AnalyticType;
import org.cardanofoundation.explorer.api.model.response.BaseFilterResponse;
import org.cardanofoundation.explorer.api.model.response.token.*;

Expand All @@ -24,7 +26,7 @@ BaseFilterResponse<TokenFilterResponse> filterToken(String query, Pageable pagea
* @param tokenId token id (fingerprint)
* @return token detail info
*/
// TokenResponse getTokenDetail(String tokenId);
TokenResponse getTokenDetail(String tokenId);

/**
* Get minting transaction by token
Expand All @@ -42,7 +44,7 @@ BaseFilterResponse<TokenFilterResponse> filterToken(String query, Pageable pagea
* @param pageable page information
* @return list addresses hold token in this page
*/
// BaseFilterResponse<TokenAddressResponse> getTopHolders(String tokenId, Pageable pageable);
BaseFilterResponse<TokenAddressResponse> getTopHolders(String tokenId, Pageable pageable);

/**
* Analysis volume of token
Expand All @@ -51,5 +53,5 @@ BaseFilterResponse<TokenFilterResponse> filterToken(String query, Pageable pagea
* @param type type of analytic
* @return list analytic volume of token
*/
// List<TokenVolumeAnalyticsResponse> getTokenVolumeAnalytic(String tokenId, AnalyticType type);
List<TokenVolumeAnalyticsResponse> getTokenVolumeAnalytic(String tokenId, AnalyticType type);
}

0 comments on commit 8607142

Please sign in to comment.