diff --git a/back-end-projects/Explorer/config/application.properties b/back-end-projects/Explorer/config/application.properties
index 2bf6b88c..848a1234 100644
--- a/back-end-projects/Explorer/config/application.properties
+++ b/back-end-projects/Explorer/config/application.properties
@@ -27,6 +27,7 @@ spring.messages.encoding=UTF-8
mybatis.check-config-location=true
mybatis.mapper-locations=classpath*:**/mapper/**/*Mapper.xml
+mybatis.configuration.mapUnderscoreToCamelCase=true
spring.profiles.active=dev
logging.config=file:config/logback.xml
diff --git a/back-end-projects/Explorer/pom.xml b/back-end-projects/Explorer/pom.xml
index 57ae5e1e..a921634d 100644
--- a/back-end-projects/Explorer/pom.xml
+++ b/back-end-projects/Explorer/pom.xml
@@ -23,6 +23,7 @@
UTF-8
1.8
2.9.2
+ 2.3.0
@@ -173,6 +174,17 @@
1.11.490
+
+ com.github.ben-manes.caffeine
+ caffeine
+
+
+
+ com.squareup.retrofit2
+ retrofit
+ ${retrofit2.version}
+
+
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/ExplorerApplication.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/ExplorerApplication.java
index 98954c74..a917a65b 100644
--- a/back-end-projects/Explorer/src/main/java/com/github/ontio/ExplorerApplication.java
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/ExplorerApplication.java
@@ -1,8 +1,11 @@
package com.github.ontio;
+import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import tk.mybatis.spring.annotation.MapperScan;
@@ -17,4 +20,10 @@ public class ExplorerApplication {
public static void main(String[] args) {
SpringApplication.run(ExplorerApplication.class, args);
}
+
+ @Bean
+ Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() {
+ return builder -> builder.serializationInclusion(JsonInclude.Include.NON_NULL);
+ }
+
}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/config/ParamsConfig.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/config/ParamsConfig.java
index 9659cf8f..849c7ca7 100644
--- a/back-end-projects/Explorer/src/main/java/com/github/ontio/config/ParamsConfig.java
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/config/ParamsConfig.java
@@ -25,12 +25,44 @@
import java.math.BigDecimal;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
@Data
@Service("ParamsConfig")
public class ParamsConfig {
+ public static final String ONT_CONTRACT_HASH = "0100000000000000000000000000000000000000";
+
+ public static final String ONG_CONTRACT_HASH = "0200000000000000000000000000000000000000";
+
+ /**
+ * 虚拟合约,表示对所有合约加总的统计
+ */
+ public static final String VIRTUAL_CONTRACT_ALL = "$$ALL$$";
+
+ /**
+ * 虚拟合约,表示对 ONT 和 ONG 加总的统计
+ */
+ public static final String VIRTUAL_CONTRACT_NATIVE = "$$NATIVE$$";
+
+ /**
+ * 虚拟合约,表示对所有 OEP4 合约加总的统计
+ */
+ public static final String VIRTUAL_CONTRACT_OEP4 = "$$OEP4$$";
+
+ private static final Collection VIRTUAL_CONTRACTS;
+
+ static {
+ Set virtualContracts = new HashSet<>(Arrays.asList(VIRTUAL_CONTRACT_ALL, VIRTUAL_CONTRACT_NATIVE,
+ VIRTUAL_CONTRACT_OEP4));
+ VIRTUAL_CONTRACTS = Collections.unmodifiableSet(virtualContracts);
+ }
+
@Value("${masternode.restful.url}")
public String MASTERNODE_RESTFUL_URL;
@@ -83,4 +115,30 @@ public interface Field {
@Value("${oep8.pumpkin.contractHash}")
public String OEP8_PUMPKIN_CONTRACTHASH;
+ @Value("${coinmarketcap.api.key}")
+ private String coinMarketCapApiKey;
+
+ @Value("${coinmarketcap.api.host:https://pro-api.coinmarketcap.com/}")
+ private String coinMarketCapApiHost;
+
+ @Value("${coinmarketcap.refresh.interval:15}")
+ private int coinMarketCapRefreshInterval;
+
+ public String getContractHash(String token) {
+ switch (token.toLowerCase()) {
+ case "ont":
+ return ONT_CONTRACT_HASH;
+ case "ong":
+ return ONG_CONTRACT_HASH;
+ case "native":
+ return VIRTUAL_CONTRACT_NATIVE;
+ case "oep4":
+ return VIRTUAL_CONTRACT_OEP4;
+ case "all":
+ return VIRTUAL_CONTRACT_ALL;
+ default:
+ throw new IllegalArgumentException("unsupported token: " + token);
+ }
+ }
+
}
\ No newline at end of file
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/controller/AddressController.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/controller/AddressController.java
index 699c336c..9e84b598 100644
--- a/back-end-projects/Explorer/src/main/java/com/github/ontio/controller/AddressController.java
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/controller/AddressController.java
@@ -10,12 +10,19 @@
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.Length;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.Pattern;
+import java.util.Date;
+import java.util.List;
/**
* @author zhouq
@@ -41,8 +48,10 @@ public AddressController(IAddressService addressService) {
@RequestLimit(count = 120)
@ApiOperation(value = "Get address balance")
@GetMapping(value = "/{address}/{token_type}/balances")
- public ResponseBean queryAddressBalance(@PathVariable("address") @Length(min = 34, max = 34, message = "Incorrect address format") String address,
- @PathVariable("token_type") @Pattern(regexp = "oep4|OEP4|oep5|OEP5|oep8|OEP8|native|NATIVE|ALL|all", message = "Incorrect token type") String tokenType) {
+ public ResponseBean queryAddressBalance(@PathVariable("address") @Length(min = 34, max = 34, message = "Incorrect address " +
+ "format") String address,
+ @PathVariable("token_type") @Pattern(regexp = "oep4|OEP4|oep5|OEP5|oep8|OEP8|native|NATIVE|ALL|all", message =
+ "Incorrect token type") String tokenType) {
log.info("####{}.{} begin...address:{},token_type:{}", CLASS_NAME, Helper.currentMethod(), address, tokenType);
@@ -54,10 +63,12 @@ public ResponseBean queryAddressBalance(@PathVariable("address") @Length(min = 3
@RequestLimit(count = 120)
@ApiOperation(value = "Get address balance by assetName")
@GetMapping(value = "/{address}/balances")
- public ResponseBean queryAddressBalanceByAssetName(@PathVariable("address") @Length(min = 34, max = 34, message = "Incorrect address format") String address,
- @RequestParam(value = "asset_name", required = false) String assetName,
- @RequestParam(value = "contract_hash", required = false) @Length(min = 40, max = 40, message = "Incorrect contract hash") String contractHash,
- @RequestParam(value = "channel", required = false) String channel) {
+ public ResponseBean queryAddressBalanceByAssetName(@PathVariable("address") @Length(min = 34, max = 34, message = "Incorrect " +
+ "address format") String address,
+ @RequestParam(value = "asset_name", required = false) String assetName,
+ @RequestParam(value = "contract_hash", required = false) @Length(min = 40, max = 40, message = "Incorrect contract " +
+ "hash") String contractHash,
+ @RequestParam(value = "channel", required = false) String channel) {
log.info("####{}.{} begin...address:{},assetName:{}", CLASS_NAME, Helper.currentMethod(), address, assetName);
@@ -75,13 +86,15 @@ public ResponseBean queryAddressBalanceByAssetName(@PathVariable("address") @Len
@RequestLimit(count = 120)
- @ApiOperation(value = "Get address transfer transaction list by params", notes = "(begin_time+end_time) or (page_number+page_size)")
+ @ApiOperation(value = "Get address transfer transaction list by params", notes = "(begin_time+end_time) or " +
+ "(page_number+page_size)")
@GetMapping(value = "/{address}/transactions")
- public ResponseBean queryAddressTransferTxsByPage(@PathVariable("address") @Length(min = 34, max = 34, message = "Incorrect address format") String address,
- @RequestParam(name = "page_size", required = false) @Min(1) @Max(20) Integer pageSize,
- @RequestParam(name = "page_number", required = false) @Min(1) Integer pageNumber,
- @RequestParam(name = "begin_time", required = false) Long beginTime,
- @RequestParam(name = "end_time", required = false) Long endTime) {
+ public ResponseBean queryAddressTransferTxsByPage(@PathVariable("address") @Length(min = 34, max = 34, message = "Incorrect " +
+ "address format") String address,
+ @RequestParam(name = "page_size", required = false) @Min(1) @Max(20) Integer pageSize,
+ @RequestParam(name = "page_number", required = false) @Min(1) Integer pageNumber,
+ @RequestParam(name = "begin_time", required = false) Long beginTime,
+ @RequestParam(name = "end_time", required = false) Long endTime) {
log.info("####{}.{} begin...address:{}", CLASS_NAME, Helper.currentMethod(), address);
@@ -100,16 +113,18 @@ public ResponseBean queryAddressTransferTxsByPage(@PathVariable("address") @Leng
}
@RequestLimit(count = 120)
- @ApiOperation(value = "Get address transfer transaction list by params+assetName", notes = "(begin_time+end_time) or (page_number+page_size) or (end_time+page_size)")
+ @ApiOperation(value = "Get address transfer transaction list by params+assetName", notes = "(begin_time+end_time) or " +
+ "(page_number+page_size) or (end_time+page_size)")
@GetMapping(value = "/{address}/{asset_name}/transactions")
- public ResponseBean queryAddressTransferTxsByPageAndAssetName(@PathVariable("address") @Length(min = 34, max = 34, message = "error address format") String address,
- @PathVariable("asset_name") String assetName,
- @RequestParam(name = "page_size", required = false) @Min(1) @Max(20) Integer pageSize,
- @RequestParam(name = "page_number", required = false) @Min(1) Integer pageNumber,
- @RequestParam(name = "begin_time", required = false) Long beginTime,
- @RequestParam(name = "end_time", required = false) Long endTime,
- @RequestParam(name = "channel", required = false) String channel,
- @RequestParam(name = "address_type", required = false) @Pattern(regexp = "fromAddress|toAddress") String addressType) {
+ public ResponseBean queryAddressTransferTxsByPageAndAssetName(@PathVariable("address") @Length(min = 34, max = 34, message =
+ "error address format") String address,
+ @PathVariable("asset_name") String assetName,
+ @RequestParam(name = "page_size", required = false) @Min(1) @Max(20) Integer pageSize,
+ @RequestParam(name = "page_number", required = false) @Min(1) Integer pageNumber,
+ @RequestParam(name = "begin_time", required = false) Long beginTime,
+ @RequestParam(name = "end_time", required = false) Long endTime,
+ @RequestParam(name = "channel", required = false) String channel,
+ @RequestParam(name = "address_type", required = false) @Pattern(regexp = "fromAddress|toAddress") String addressType) {
log.info("###{}.{} begin...address:{}", CLASS_NAME, Helper.currentMethod(), address);
@@ -139,5 +154,44 @@ public ResponseBean queryAddressTransferTxsByPageAndAssetName(@PathVariable("add
return rs;
}
+ @RequestLimit(count = 120)
+ @ApiOperation(value = "Get address daily aggregations by ont/ong token")
+ @GetMapping(value = "/{address}/daily")
+ public ResponseBean queryDailyAggregation(
+ @PathVariable("address") @Length(min = 34, max = 40, message = "Incorrect address format") String address,
+ @RequestParam(value = "token") @Pattern(regexp = "ont|ONT|ong|ONG", message = "Incorrect token") String token,
+ @RequestParam(name = "from", required = false) @DateTimeFormat(pattern = "yyyyMMdd") Date from,
+ @RequestParam(name = "to", required = false) @DateTimeFormat(pattern = "yyyyMMdd") Date to
+ ) {
+ log.info("###{}.{} begin...address:{}", CLASS_NAME, Helper.currentMethod(), address);
+
+ return addressService.queryDailyAggregation(address, token, from, to);
+ }
+
+ @RequestLimit(count = 120)
+ @ApiOperation(value = "Get address daily aggregations by specific token type")
+ @GetMapping(value = "/{address}/{token_type}/daily")
+ public ResponseBean queryDailyAggregationOfTokenType(
+ @PathVariable("address") @Length(min = 34, max = 40, message = "Incorrect address format") String address,
+ @PathVariable(value = "token_type") @Pattern(regexp = "oep4|OEP4|native|NATIVE", message = "Incorrect token type") String tokenType,
+ @RequestParam(name = "from", required = false) @DateTimeFormat(pattern = "yyyyMMdd") Date from,
+ @RequestParam(name = "to", required = false) @DateTimeFormat(pattern = "yyyyMMdd") Date to
+ ) {
+ log.info("###{}.{} begin...address:{}", CLASS_NAME, Helper.currentMethod(), address);
+
+ return addressService.queryDailyAggregationOfTokenType(address, tokenType, from, to);
+ }
+
+ @RequestLimit(count = 120)
+ @ApiOperation(value = "Get address daily rankings by ranking ids and ranking duration")
+ @GetMapping(value = "/rankings")
+ public ResponseBean queryRankings(
+ @RequestParam(name = "ranking_id", required = false) List rankingIds,
+ @RequestParam("duration") short duration
+ ) {
+ log.info("###{}.{} begin...", CLASS_NAME, Helper.currentMethod());
+
+ return addressService.queryRankings(rankingIds, duration);
+ }
}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/controller/ContractController.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/controller/ContractController.java
index 6ba5ce74..1465fe85 100644
--- a/back-end-projects/Explorer/src/main/java/com/github/ontio/controller/ContractController.java
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/controller/ContractController.java
@@ -26,12 +26,18 @@
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.Length;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.Pattern;
+import java.util.Date;
@Slf4j
@Validated
@@ -153,5 +159,32 @@ public ResponseBean queryDappstoreDappsSummary() {
return contractService.queryDappstoreDappsSummary();
}
+ @RequestLimit(count = 120)
+ @ApiOperation(value = "Get contract daily aggregations by ont/ong token")
+ @GetMapping(value = "/{contract_hash}/daily")
+ public ResponseBean queryDailyAggregation(
+ @PathVariable("contract_hash") @Length(min = 40, max = 40, message = "Incorrect contract hash") String contractHash,
+ @RequestParam(value = "token") @Pattern(regexp = "ont|ONT|ong|ONG", message = "Incorrect token") String token,
+ @RequestParam(name = "from", required = false) @DateTimeFormat(pattern = "yyyyMMdd") Date from,
+ @RequestParam(name = "to", required = false) @DateTimeFormat(pattern = "yyyyMMdd") Date to
+ ) {
+ log.info("####{}.{} begin...contract_hash:{}", CLASS_NAME, Helper.currentMethod(), contractHash);
+
+ return contractService.queryDailyAggregation(contractHash, token, from, to);
+ }
+
+ @RequestLimit(count = 120)
+ @ApiOperation(value = "Get address daily aggregations by specific token type")
+ @GetMapping(value = "/{contract_hash}/{token_type}/daily")
+ public ResponseBean queryDailyAggregationOfTokenType(
+ @PathVariable("contract_hash") @Length(min = 40, max = 40, message = "Incorrect contract hash") String contractHash,
+ @PathVariable(value = "token_type") @Pattern(regexp = "oep4|OEP4|native|NATIVE", message = "Incorrect token type") String tokenType,
+ @RequestParam(name = "from", required = false) @DateTimeFormat(pattern = "yyyyMMdd") Date from,
+ @RequestParam(name = "to", required = false) @DateTimeFormat(pattern = "yyyyMMdd") Date to
+ ) {
+ log.info("####{}.{} begin...contract_hash:{}", CLASS_NAME, Helper.currentMethod(), contractHash);
+
+ return contractService.queryDailyAggregationOfTokenType(contractHash, tokenType, from, to);
+ }
}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/controller/TokenController.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/controller/TokenController.java
index f211674d..4dd6aa75 100644
--- a/back-end-projects/Explorer/src/main/java/com/github/ontio/controller/TokenController.java
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/controller/TokenController.java
@@ -8,12 +8,19 @@
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.Length;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.Pattern;
+import java.util.Date;
+import java.util.List;
/**
* @author zhouq
@@ -63,10 +70,11 @@ public ResponseBean queryTokenDetail(@PathVariable("token_type") @Pattern(regexp
@RequestLimit(count = 120)
@ApiOperation(value = "Get oep8 token transaction list by token name")
@GetMapping(value = "/oep8/{contract_hash}/{token_name}/transactions")
- public ResponseBean queryOep8TxsByPage(@PathVariable("contract_hash") @Length(min = 40, max = 40, message = "Incorrect contract hash") String contractHash,
- @PathVariable("token_name") String tokenName,
- @RequestParam("page_size") @Min(1) @Max(20) Integer pageSize,
- @RequestParam("page_number") @Min(1) Integer pageNumber) {
+ public ResponseBean queryOep8TxsByPage(@PathVariable("contract_hash") @Length(min = 40, max = 40, message = "Incorrect " +
+ "contract hash") String contractHash,
+ @PathVariable("token_name") String tokenName,
+ @RequestParam("page_size") @Min(1) @Max(20) Integer pageSize,
+ @RequestParam("page_number") @Min(1) Integer pageNumber) {
log.info("###{}.{} begin...contract_hash:{},token_name:{}", CLASS_NAME, Helper.currentMethod(), contractHash, tokenName);
@@ -74,5 +82,42 @@ public ResponseBean queryOep8TxsByPage(@PathVariable("contract_hash") @Length(mi
return rs;
}
+ @RequestLimit(count = 120)
+ @ApiOperation(value = "Get token daily aggregations for specific token type")
+ @GetMapping(value = "/{token_type}/{contract_hash}/daily")
+ public ResponseBean queryDailyAggregation(
+ @PathVariable("token_type") @Pattern(regexp = "oep4|OEP4", message = "Incorrect token type") String tokenType,
+ @PathVariable("contract_hash") @Length(min = 40, max = 40, message = "Incorrect contract hash") String contractHash,
+ @RequestParam(name = "from", required = false) @DateTimeFormat(pattern = "yyyyMMdd") Date from,
+ @RequestParam(name = "to", required = false) @DateTimeFormat(pattern = "yyyyMMdd") Date to
+ ) {
+ log.info("###{}.{} begin...token_type:{},contract_hash:{}", CLASS_NAME, Helper.currentMethod(), tokenType, contractHash);
+
+ return tokenService.queryDailyAggregations(tokenType, contractHash, from, to);
+ }
+
+ @RequestLimit(count = 120)
+ @ApiOperation(value = "Get token rankings")
+ @GetMapping(value = "/rankings")
+ public ResponseBean queryRankings(
+ @RequestParam(name = "ranking_id", required = false) List rankingIds,
+ @RequestParam("duration") short duration
+ ) {
+ log.info("###{}.{} begin...", CLASS_NAME, Helper.currentMethod());
+
+ return tokenService.queryRankings(rankingIds, duration);
+ }
+
+ @RequestLimit(count = 120)
+ @ApiOperation(value = "Get token price in fiat")
+ @GetMapping(value = "/prices")
+ public ResponseBean queryPrice(
+ @RequestParam("token") @Pattern(regexp = "ont|ONT|ong|ONG", message = "Incorrect token") String token,
+ @RequestParam("fiat") @Pattern(regexp = "usd|USD", message = "Incorrect fiat") String fiat
+ ) {
+ log.info("###{}.{} begin...", CLASS_NAME, Helper.currentMethod());
+
+ return tokenService.queryPrice(token, fiat);
+ }
}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/mapper/AddressDailyAggregationMapper.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/mapper/AddressDailyAggregationMapper.java
new file mode 100644
index 00000000..c3e950c9
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/mapper/AddressDailyAggregationMapper.java
@@ -0,0 +1,26 @@
+package com.github.ontio.mapper;
+
+import com.github.ontio.model.dao.AddressDailyAggregation;
+import com.github.ontio.model.dto.aggregation.AddressAggregationDto;
+import com.github.ontio.model.dto.aggregation.ExtremeBalanceDto;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+import tk.mybatis.mapper.common.Mapper;
+
+import java.util.Date;
+import java.util.List;
+
+@Repository
+public interface AddressDailyAggregationMapper extends Mapper {
+
+ List findAggregations(@Param("address") String address,
+ @Param("tokenContractHash") String tokenContractHash, @Param("from") Date from, @Param("to") Date to);
+
+ List findAggregationsForToken(@Param("address") String address,
+ @Param("tokenContractHash") String tokenContractHash, @Param("from") Date from, @Param("to") Date to);
+
+ ExtremeBalanceDto findMaxBalance(@Param("address") String address, @Param("tokenContractHash") String tokenContractHash);
+
+ ExtremeBalanceDto findMinBalance(@Param("address") String address, @Param("tokenContractHash") String tokenContractHash);
+
+}
\ No newline at end of file
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/mapper/ContractDailyAggregationMapper.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/mapper/ContractDailyAggregationMapper.java
new file mode 100644
index 00000000..89e5e920
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/mapper/ContractDailyAggregationMapper.java
@@ -0,0 +1,21 @@
+package com.github.ontio.mapper;
+
+import com.github.ontio.model.dao.ContractDailyAggregation;
+import com.github.ontio.model.dto.aggregation.ContractAggregationDto;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+import tk.mybatis.mapper.common.Mapper;
+
+import java.util.Date;
+import java.util.List;
+
+@Repository
+public interface ContractDailyAggregationMapper extends Mapper {
+
+ List findAggregations(@Param("contractHash") String contractHash,
+ @Param("tokenContractHash") String tokenContractHash, @Param("from") Date from, @Param("to") Date to);
+
+ List findAggregationsForToken(@Param("contractHash") String contractHash,
+ @Param("tokenContractHash") String tokenContractHash, @Param("from") Date from, @Param("to") Date to);
+
+}
\ No newline at end of file
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/mapper/RankingMapper.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/mapper/RankingMapper.java
new file mode 100644
index 00000000..a367e01f
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/mapper/RankingMapper.java
@@ -0,0 +1,28 @@
+package com.github.ontio.mapper;
+
+import com.github.ontio.model.dao.Ranking;
+import com.github.ontio.model.dto.ranking.AddressRankingDto;
+import com.github.ontio.model.dto.ranking.TokenRankingDto;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+import tk.mybatis.mapper.common.Mapper;
+
+import java.util.List;
+
+@Repository
+public interface RankingMapper extends Mapper {
+
+ /**
+ * 排名分组:地址排名
+ */
+ short RANKING_GROUP_ADDRESS = 1;
+ /**
+ * 排名分组:Token 排名
+ */
+ short RANKING_GROUP_TOKEN = 2;
+
+ List findAddressRankings(@Param("rankingIds") List rankingIds, @Param("duration") short duration);
+
+ List findTokenRankings(@Param("rankingIds") List rankingIds, @Param("duration") short duration);
+
+}
\ No newline at end of file
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/mapper/TokenDailyAggregationMapper.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/mapper/TokenDailyAggregationMapper.java
new file mode 100644
index 00000000..abb65c7c
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/mapper/TokenDailyAggregationMapper.java
@@ -0,0 +1,18 @@
+package com.github.ontio.mapper;
+
+import com.github.ontio.model.dao.TokenDailyAggregation;
+import com.github.ontio.model.dto.aggregation.TokenAggregationDto;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+import tk.mybatis.mapper.common.Mapper;
+
+import java.util.Date;
+import java.util.List;
+
+@Repository
+public interface TokenDailyAggregationMapper extends Mapper {
+
+ List findAggregations(@Param("contractHash") String contractHash, @Param("from") Date from,
+ @Param("to") Date to);
+
+}
\ No newline at end of file
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dao/AddressDailyAggregation.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dao/AddressDailyAggregation.java
new file mode 100644
index 00000000..4cc2028b
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dao/AddressDailyAggregation.java
@@ -0,0 +1,432 @@
+package com.github.ontio.model.dao;
+
+import javax.persistence.Column;
+import javax.persistence.Table;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Table(name = "tbl_address_daily_aggregation")
+public class AddressDailyAggregation {
+ /**
+ * 地址
+ */
+ private String address;
+
+ /**
+ * Token合约hash
+ */
+ @Column(name = "token_contract_hash")
+ private String tokenContractHash;
+
+ /**
+ * 日期维度ID
+ */
+ @Column(name = "date_id")
+ private Integer dateId;
+
+ /**
+ * 日终余额
+ */
+ private BigDecimal balance;
+
+ /**
+ * 当天USD价格
+ */
+ @Column(name = "usd_price")
+ private BigDecimal usdPrice;
+
+ /**
+ * 最高余额
+ */
+ @Column(name = "max_balance")
+ private BigDecimal maxBalance;
+
+ /**
+ * 最低余额
+ */
+ @Column(name = "min_balance")
+ private BigDecimal minBalance;
+
+ /**
+ * 入金交易数量
+ */
+ @Column(name = "deposit_tx_count")
+ private Integer depositTxCount;
+
+ /**
+ * 出金交易数量
+ */
+ @Column(name = "withdraw_tx_count")
+ private Integer withdrawTxCount;
+
+ /**
+ * 入金金额
+ */
+ @Column(name = "deposit_amount")
+ private BigDecimal depositAmount;
+
+ /**
+ * 出金金额
+ */
+ @Column(name = "withdraw_amount")
+ private BigDecimal withdrawAmount;
+
+ /**
+ * 去重入金地址数量
+ */
+ @Column(name = "deposit_address_count")
+ private Integer depositAddressCount;
+
+ /**
+ * 去重出金地址数量
+ */
+ @Column(name = "withdraw_address_count")
+ private Integer withdrawAddressCount;
+
+ /**
+ * 去重交易地址数量
+ */
+ @Column(name = "tx_address_count")
+ private Integer txAddressCount;
+
+ /**
+ * 消耗手续费总额
+ */
+ @Column(name = "fee_amount")
+ private BigDecimal feeAmount;
+
+ /**
+ * 调用合约数量,只适用于虚拟Token统计
+ */
+ @Column(name = "contract_count")
+ private Integer contractCount;
+
+ /**
+ * 是否为虚拟Token统计
+ */
+ @Column(name = "is_virtual")
+ private Boolean isVirtual;
+
+ @Column(name = "update_time")
+ private Date updateTime;
+
+ /**
+ * 获取地址
+ *
+ * @return address - 地址
+ */
+ public String getAddress() {
+ return address;
+ }
+
+ /**
+ * 设置地址
+ *
+ * @param address 地址
+ */
+ public void setAddress(String address) {
+ this.address = address == null ? null : address.trim();
+ }
+
+ /**
+ * 获取Token合约hash
+ *
+ * @return token_contract_hash - Token合约hash
+ */
+ public String getTokenContractHash() {
+ return tokenContractHash;
+ }
+
+ /**
+ * 设置Token合约hash
+ *
+ * @param tokenContractHash Token合约hash
+ */
+ public void setTokenContractHash(String tokenContractHash) {
+ this.tokenContractHash = tokenContractHash == null ? null : tokenContractHash.trim();
+ }
+
+ /**
+ * 获取日期维度ID
+ *
+ * @return date_id - 日期维度ID
+ */
+ public Integer getDateId() {
+ return dateId;
+ }
+
+ /**
+ * 设置日期维度ID
+ *
+ * @param dateId 日期维度ID
+ */
+ public void setDateId(Integer dateId) {
+ this.dateId = dateId;
+ }
+
+ /**
+ * 获取日终余额
+ *
+ * @return balance - 日终余额
+ */
+ public BigDecimal getBalance() {
+ return balance;
+ }
+
+ /**
+ * 设置日终余额
+ *
+ * @param balance 日终余额
+ */
+ public void setBalance(BigDecimal balance) {
+ this.balance = balance;
+ }
+
+ /**
+ * 获取当天USD价格
+ *
+ * @return usd_price - 当天USD价格
+ */
+ public BigDecimal getUsdPrice() {
+ return usdPrice;
+ }
+
+ /**
+ * 设置当天USD价格
+ *
+ * @param usdPrice 当天USD价格
+ */
+ public void setUsdPrice(BigDecimal usdPrice) {
+ this.usdPrice = usdPrice;
+ }
+
+ /**
+ * 获取最高余额
+ *
+ * @return max_balance - 最高余额
+ */
+ public BigDecimal getMaxBalance() {
+ return maxBalance;
+ }
+
+ /**
+ * 设置最高余额
+ *
+ * @param maxBalance 最高余额
+ */
+ public void setMaxBalance(BigDecimal maxBalance) {
+ this.maxBalance = maxBalance;
+ }
+
+ /**
+ * 获取最低余额
+ *
+ * @return min_balance - 最低余额
+ */
+ public BigDecimal getMinBalance() {
+ return minBalance;
+ }
+
+ /**
+ * 设置最低余额
+ *
+ * @param minBalance 最低余额
+ */
+ public void setMinBalance(BigDecimal minBalance) {
+ this.minBalance = minBalance;
+ }
+
+ /**
+ * 获取入金交易数量
+ *
+ * @return deposit_tx_count - 入金交易数量
+ */
+ public Integer getDepositTxCount() {
+ return depositTxCount;
+ }
+
+ /**
+ * 设置入金交易数量
+ *
+ * @param depositTxCount 入金交易数量
+ */
+ public void setDepositTxCount(Integer depositTxCount) {
+ this.depositTxCount = depositTxCount;
+ }
+
+ /**
+ * 获取出金交易数量
+ *
+ * @return withdraw_tx_count - 出金交易数量
+ */
+ public Integer getWithdrawTxCount() {
+ return withdrawTxCount;
+ }
+
+ /**
+ * 设置出金交易数量
+ *
+ * @param withdrawTxCount 出金交易数量
+ */
+ public void setWithdrawTxCount(Integer withdrawTxCount) {
+ this.withdrawTxCount = withdrawTxCount;
+ }
+
+ /**
+ * 获取入金金额
+ *
+ * @return deposit_amount - 入金金额
+ */
+ public BigDecimal getDepositAmount() {
+ return depositAmount;
+ }
+
+ /**
+ * 设置入金金额
+ *
+ * @param depositAmount 入金金额
+ */
+ public void setDepositAmount(BigDecimal depositAmount) {
+ this.depositAmount = depositAmount;
+ }
+
+ /**
+ * 获取出金金额
+ *
+ * @return withdraw_amount - 出金金额
+ */
+ public BigDecimal getWithdrawAmount() {
+ return withdrawAmount;
+ }
+
+ /**
+ * 设置出金金额
+ *
+ * @param withdrawAmount 出金金额
+ */
+ public void setWithdrawAmount(BigDecimal withdrawAmount) {
+ this.withdrawAmount = withdrawAmount;
+ }
+
+ /**
+ * 获取去重入金地址数量
+ *
+ * @return deposit_address_count - 去重入金地址数量
+ */
+ public Integer getDepositAddressCount() {
+ return depositAddressCount;
+ }
+
+ /**
+ * 设置去重入金地址数量
+ *
+ * @param depositAddressCount 去重入金地址数量
+ */
+ public void setDepositAddressCount(Integer depositAddressCount) {
+ this.depositAddressCount = depositAddressCount;
+ }
+
+ /**
+ * 获取去重出金地址数量
+ *
+ * @return withdraw_address_count - 去重出金地址数量
+ */
+ public Integer getWithdrawAddressCount() {
+ return withdrawAddressCount;
+ }
+
+ /**
+ * 设置去重出金地址数量
+ *
+ * @param withdrawAddressCount 去重出金地址数量
+ */
+ public void setWithdrawAddressCount(Integer withdrawAddressCount) {
+ this.withdrawAddressCount = withdrawAddressCount;
+ }
+
+ /**
+ * 获取去重交易地址数量
+ *
+ * @return tx_address_count - 去重交易地址数量
+ */
+ public Integer getTxAddressCount() {
+ return txAddressCount;
+ }
+
+ /**
+ * 设置去重交易地址数量
+ *
+ * @param txAddressCount 去重交易地址数量
+ */
+ public void setTxAddressCount(Integer txAddressCount) {
+ this.txAddressCount = txAddressCount;
+ }
+
+ /**
+ * 获取消耗手续费总额
+ *
+ * @return fee_amount - 消耗手续费总额
+ */
+ public BigDecimal getFeeAmount() {
+ return feeAmount;
+ }
+
+ /**
+ * 设置消耗手续费总额
+ *
+ * @param feeAmount 消耗手续费总额
+ */
+ public void setFeeAmount(BigDecimal feeAmount) {
+ this.feeAmount = feeAmount;
+ }
+
+ /**
+ * 获取调用合约数量,只适用于虚拟Token统计
+ *
+ * @return contract_count - 调用合约数量,只适用于虚拟Token统计
+ */
+ public Integer getContractCount() {
+ return contractCount;
+ }
+
+ /**
+ * 设置调用合约数量,只适用于虚拟Token统计
+ *
+ * @param contractCount 调用合约数量,只适用于虚拟Token统计
+ */
+ public void setContractCount(Integer contractCount) {
+ this.contractCount = contractCount;
+ }
+
+ /**
+ * 获取是否为虚拟Token统计
+ *
+ * @return is_virtual - 是否为虚拟Token统计
+ */
+ public Boolean getIsVirtual() {
+ return isVirtual;
+ }
+
+ /**
+ * 设置是否为虚拟Token统计
+ *
+ * @param isVirtual 是否为虚拟Token统计
+ */
+ public void setIsVirtual(Boolean isVirtual) {
+ this.isVirtual = isVirtual;
+ }
+
+ /**
+ * @return update_time
+ */
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+
+ /**
+ * @param updateTime
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+}
\ No newline at end of file
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dao/ContractDailyAggregation.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dao/ContractDailyAggregation.java
new file mode 100644
index 00000000..ad6dfe31
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dao/ContractDailyAggregation.java
@@ -0,0 +1,290 @@
+package com.github.ontio.model.dao;
+
+import javax.persistence.Column;
+import javax.persistence.Table;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Table(name = "tbl_contract_daily_aggregation")
+public class ContractDailyAggregation {
+ /**
+ * 合约hash
+ */
+ @Column(name = "contract_hash")
+ private String contractHash;
+
+ /**
+ * Token合约hash
+ */
+ @Column(name = "token_contract_hash")
+ private String tokenContractHash;
+
+ /**
+ * 日期维度ID
+ */
+ @Column(name = "date_id")
+ private Integer dateId;
+
+ /**
+ * 交易数量
+ */
+ @Column(name = "tx_count")
+ private Integer txCount;
+
+ /**
+ * 交易金额
+ */
+ @Column(name = "tx_amount")
+ private BigDecimal txAmount;
+
+ /**
+ * 去重入金交易地址数量
+ */
+ @Column(name = "deposit_address_count")
+ private Integer depositAddressCount;
+
+ /**
+ * 去重出金交易地址数量
+ */
+ @Column(name = "withdraw_address_count")
+ private Integer withdrawAddressCount;
+
+ /**
+ * 去重交易地址数量
+ */
+ @Column(name = "tx_address_count")
+ private Integer txAddressCount;
+
+ /**
+ * 消耗手续费总额
+ */
+ @Column(name = "fee_amount")
+ private BigDecimal feeAmount;
+
+ /**
+ * 调用合约数量,只适用于虚拟Token统计
+ */
+ @Column(name = "contract_count")
+ private Integer contractCount;
+
+ /**
+ * 是否为虚拟Token统计
+ */
+ @Column(name = "is_virtual")
+ private Boolean isVirtual;
+
+ @Column(name = "update_time")
+ private Date updateTime;
+
+ /**
+ * 获取合约hash
+ *
+ * @return contract_hash - 合约hash
+ */
+ public String getContractHash() {
+ return contractHash;
+ }
+
+ /**
+ * 设置合约hash
+ *
+ * @param contractHash 合约hash
+ */
+ public void setContractHash(String contractHash) {
+ this.contractHash = contractHash == null ? null : contractHash.trim();
+ }
+
+ /**
+ * 获取Token合约hash
+ *
+ * @return token_contract_hash - Token合约hash
+ */
+ public String getTokenContractHash() {
+ return tokenContractHash;
+ }
+
+ /**
+ * 设置Token合约hash
+ *
+ * @param tokenContractHash Token合约hash
+ */
+ public void setTokenContractHash(String tokenContractHash) {
+ this.tokenContractHash = tokenContractHash == null ? null : tokenContractHash.trim();
+ }
+
+ /**
+ * 获取日期维度ID
+ *
+ * @return date_id - 日期维度ID
+ */
+ public Integer getDateId() {
+ return dateId;
+ }
+
+ /**
+ * 设置日期维度ID
+ *
+ * @param dateId 日期维度ID
+ */
+ public void setDateId(Integer dateId) {
+ this.dateId = dateId;
+ }
+
+ /**
+ * 获取交易数量
+ *
+ * @return tx_count - 交易数量
+ */
+ public Integer getTxCount() {
+ return txCount;
+ }
+
+ /**
+ * 设置交易数量
+ *
+ * @param txCount 交易数量
+ */
+ public void setTxCount(Integer txCount) {
+ this.txCount = txCount;
+ }
+
+ /**
+ * 获取交易金额
+ *
+ * @return tx_amount - 交易金额
+ */
+ public BigDecimal getTxAmount() {
+ return txAmount;
+ }
+
+ /**
+ * 设置交易金额
+ *
+ * @param txAmount 交易金额
+ */
+ public void setTxAmount(BigDecimal txAmount) {
+ this.txAmount = txAmount;
+ }
+
+ /**
+ * 获取去重入金交易地址数量
+ *
+ * @return deposit_address_count - 去重入金交易地址数量
+ */
+ public Integer getDepositAddressCount() {
+ return depositAddressCount;
+ }
+
+ /**
+ * 设置去重入金交易地址数量
+ *
+ * @param depositAddressCount 去重入金交易地址数量
+ */
+ public void setDepositAddressCount(Integer depositAddressCount) {
+ this.depositAddressCount = depositAddressCount;
+ }
+
+ /**
+ * 获取去重出金交易地址数量
+ *
+ * @return withdraw_address_count - 去重出金交易地址数量
+ */
+ public Integer getWithdrawAddressCount() {
+ return withdrawAddressCount;
+ }
+
+ /**
+ * 设置去重出金交易地址数量
+ *
+ * @param withdrawAddressCount 去重出金交易地址数量
+ */
+ public void setWithdrawAddressCount(Integer withdrawAddressCount) {
+ this.withdrawAddressCount = withdrawAddressCount;
+ }
+
+ /**
+ * 获取去重交易地址数量
+ *
+ * @return tx_address_count - 去重交易地址数量
+ */
+ public Integer getTxAddressCount() {
+ return txAddressCount;
+ }
+
+ /**
+ * 设置去重交易地址数量
+ *
+ * @param txAddressCount 去重交易地址数量
+ */
+ public void setTxAddressCount(Integer txAddressCount) {
+ this.txAddressCount = txAddressCount;
+ }
+
+ /**
+ * 获取消耗手续费总额
+ *
+ * @return fee_amount - 消耗手续费总额
+ */
+ public BigDecimal getFeeAmount() {
+ return feeAmount;
+ }
+
+ /**
+ * 设置消耗手续费总额
+ *
+ * @param feeAmount 消耗手续费总额
+ */
+ public void setFeeAmount(BigDecimal feeAmount) {
+ this.feeAmount = feeAmount;
+ }
+
+ /**
+ * 获取调用合约数量,只适用于虚拟Token统计
+ *
+ * @return contract_count - 调用合约数量,只适用于虚拟Token统计
+ */
+ public Integer getContractCount() {
+ return contractCount;
+ }
+
+ /**
+ * 设置调用合约数量,只适用于虚拟Token统计
+ *
+ * @param contractCount 调用合约数量,只适用于虚拟Token统计
+ */
+ public void setContractCount(Integer contractCount) {
+ this.contractCount = contractCount;
+ }
+
+ /**
+ * 获取是否为虚拟Token统计
+ *
+ * @return is_virtual - 是否为虚拟Token统计
+ */
+ public Boolean getIsVirtual() {
+ return isVirtual;
+ }
+
+ /**
+ * 设置是否为虚拟Token统计
+ *
+ * @param isVirtual 是否为虚拟Token统计
+ */
+ public void setIsVirtual(Boolean isVirtual) {
+ this.isVirtual = isVirtual;
+ }
+
+ /**
+ * @return update_time
+ */
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+
+ /**
+ * @param updateTime
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+}
\ No newline at end of file
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dao/Ranking.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dao/Ranking.java
new file mode 100644
index 00000000..5317aad0
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dao/Ranking.java
@@ -0,0 +1,190 @@
+package com.github.ontio.model.dao;
+
+import javax.persistence.Column;
+import javax.persistence.Table;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Table(name = "tbl_ranking")
+public class Ranking {
+ /**
+ * 排名分组,由业务系统决定
+ */
+ @Column(name = "ranking_group")
+ private Short rankingGroup;
+
+ /**
+ * 具体排名,由业务系统决定
+ */
+ @Column(name = "ranking_id")
+ private Short rankingId;
+
+ /**
+ * 排名区间,1:24小时;3:3天;7:7天
+ */
+ @Column(name = "ranking_duration")
+ private Short rankingDuration;
+
+ /**
+ * 排名数,1 - N
+ */
+ private Short ranking;
+
+ /**
+ * 排名对象,根据不同的排名有不同含义
+ */
+ private String member;
+
+ /**
+ * 排名数值
+ */
+ private BigDecimal amount;
+
+ /**
+ * 占比
+ */
+ private BigDecimal percentage;
+
+ @Column(name = "update_time")
+ private Date updateTime;
+
+ /**
+ * 获取排名分组,由业务系统决定
+ *
+ * @return ranking_group - 排名分组,由业务系统决定
+ */
+ public Short getRankingGroup() {
+ return rankingGroup;
+ }
+
+ /**
+ * 设置排名分组,由业务系统决定
+ *
+ * @param rankingGroup 排名分组,由业务系统决定
+ */
+ public void setRankingGroup(Short rankingGroup) {
+ this.rankingGroup = rankingGroup;
+ }
+
+ /**
+ * 获取具体排名,由业务系统决定
+ *
+ * @return ranking_id - 具体排名,由业务系统决定
+ */
+ public Short getRankingId() {
+ return rankingId;
+ }
+
+ /**
+ * 设置具体排名,由业务系统决定
+ *
+ * @param rankingId 具体排名,由业务系统决定
+ */
+ public void setRankingId(Short rankingId) {
+ this.rankingId = rankingId;
+ }
+
+ /**
+ * 获取排名区间,1:24小时;3:3天;7:7天
+ *
+ * @return ranking_duration - 排名区间,1:24小时;3:3天;7:7天
+ */
+ public Short getRankingDuration() {
+ return rankingDuration;
+ }
+
+ /**
+ * 设置排名区间,1:24小时;3:3天;7:7天
+ *
+ * @param rankingDuration 排名区间,1:24小时;3:3天;7:7天
+ */
+ public void setRankingDuration(Short rankingDuration) {
+ this.rankingDuration = rankingDuration;
+ }
+
+ /**
+ * 获取排名数,1 - N
+ *
+ * @return ranking - 排名数,1 - N
+ */
+ public Short getRanking() {
+ return ranking;
+ }
+
+ /**
+ * 设置排名数,1 - N
+ *
+ * @param ranking 排名数,1 - N
+ */
+ public void setRanking(Short ranking) {
+ this.ranking = ranking;
+ }
+
+ /**
+ * 获取排名对象,根据不同的排名有不同含义
+ *
+ * @return member - 排名对象,根据不同的排名有不同含义
+ */
+ public String getMember() {
+ return member;
+ }
+
+ /**
+ * 设置排名对象,根据不同的排名有不同含义
+ *
+ * @param member 排名对象,根据不同的排名有不同含义
+ */
+ public void setMember(String member) {
+ this.member = member == null ? null : member.trim();
+ }
+
+ /**
+ * 获取排名数值
+ *
+ * @return amount - 排名数值
+ */
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ /**
+ * 设置排名数值
+ *
+ * @param amount 排名数值
+ */
+ public void setAmount(BigDecimal amount) {
+ this.amount = amount;
+ }
+
+ /**
+ * 获取占比
+ *
+ * @return percentage - 占比
+ */
+ public BigDecimal getPercentage() {
+ return percentage;
+ }
+
+ /**
+ * 设置占比
+ *
+ * @param percentage 占比
+ */
+ public void setPercentage(BigDecimal percentage) {
+ this.percentage = percentage;
+ }
+
+ /**
+ * @return update_time
+ */
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+
+ /**
+ * @param updateTime
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+}
\ No newline at end of file
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dao/TokenDailyAggregation.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dao/TokenDailyAggregation.java
new file mode 100644
index 00000000..1b6b98ff
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dao/TokenDailyAggregation.java
@@ -0,0 +1,242 @@
+package com.github.ontio.model.dao;
+
+import javax.persistence.Column;
+import javax.persistence.Table;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Table(name = "tbl_token_daily_aggregation")
+public class TokenDailyAggregation {
+ /**
+ * Token合约hash
+ */
+ @Column(name = "token_contract_hash")
+ private String tokenContractHash;
+
+ /**
+ * 日期维度ID
+ */
+ @Column(name = "date_id")
+ private Integer dateId;
+
+ /**
+ * 当天USD价格
+ */
+ @Column(name = "usd_price")
+ private BigDecimal usdPrice;
+
+ /**
+ * 交易数量
+ */
+ @Column(name = "tx_count")
+ private Integer txCount;
+
+ /**
+ * 交易金额
+ */
+ @Column(name = "tx_amount")
+ private BigDecimal txAmount;
+
+ /**
+ * 去重入金地址数量
+ */
+ @Column(name = "deposit_address_count")
+ private Integer depositAddressCount;
+
+ /**
+ * 去重出金地址数量
+ */
+ @Column(name = "withdraw_address_count")
+ private Integer withdrawAddressCount;
+
+ /**
+ * 去重交易地址数量
+ */
+ @Column(name = "tx_address_count")
+ private Integer txAddressCount;
+
+ /**
+ * 消耗手续费总额
+ */
+ @Column(name = "fee_amount")
+ private BigDecimal feeAmount;
+
+ @Column(name = "update_time")
+ private Date updateTime;
+
+ /**
+ * 获取Token合约hash
+ *
+ * @return token_contract_hash - Token合约hash
+ */
+ public String getTokenContractHash() {
+ return tokenContractHash;
+ }
+
+ /**
+ * 设置Token合约hash
+ *
+ * @param tokenContractHash Token合约hash
+ */
+ public void setTokenContractHash(String tokenContractHash) {
+ this.tokenContractHash = tokenContractHash == null ? null : tokenContractHash.trim();
+ }
+
+ /**
+ * 获取日期维度ID
+ *
+ * @return date_id - 日期维度ID
+ */
+ public Integer getDateId() {
+ return dateId;
+ }
+
+ /**
+ * 设置日期维度ID
+ *
+ * @param dateId 日期维度ID
+ */
+ public void setDateId(Integer dateId) {
+ this.dateId = dateId;
+ }
+
+ /**
+ * 获取当天USD价格
+ *
+ * @return usd_price - 当天USD价格
+ */
+ public BigDecimal getUsdPrice() {
+ return usdPrice;
+ }
+
+ /**
+ * 设置当天USD价格
+ *
+ * @param usdPrice 当天USD价格
+ */
+ public void setUsdPrice(BigDecimal usdPrice) {
+ this.usdPrice = usdPrice;
+ }
+
+ /**
+ * 获取交易数量
+ *
+ * @return tx_count - 交易数量
+ */
+ public Integer getTxCount() {
+ return txCount;
+ }
+
+ /**
+ * 设置交易数量
+ *
+ * @param txCount 交易数量
+ */
+ public void setTxCount(Integer txCount) {
+ this.txCount = txCount;
+ }
+
+ /**
+ * 获取交易金额
+ *
+ * @return tx_amount - 交易金额
+ */
+ public BigDecimal getTxAmount() {
+ return txAmount;
+ }
+
+ /**
+ * 设置交易金额
+ *
+ * @param txAmount 交易金额
+ */
+ public void setTxAmount(BigDecimal txAmount) {
+ this.txAmount = txAmount;
+ }
+
+ /**
+ * 获取去重入金地址数量
+ *
+ * @return deposit_address_count - 去重入金地址数量
+ */
+ public Integer getDepositAddressCount() {
+ return depositAddressCount;
+ }
+
+ /**
+ * 设置去重入金地址数量
+ *
+ * @param depositAddressCount 去重入金地址数量
+ */
+ public void setDepositAddressCount(Integer depositAddressCount) {
+ this.depositAddressCount = depositAddressCount;
+ }
+
+ /**
+ * 获取去重出金地址数量
+ *
+ * @return withdraw_address_count - 去重出金地址数量
+ */
+ public Integer getWithdrawAddressCount() {
+ return withdrawAddressCount;
+ }
+
+ /**
+ * 设置去重出金地址数量
+ *
+ * @param withdrawAddressCount 去重出金地址数量
+ */
+ public void setWithdrawAddressCount(Integer withdrawAddressCount) {
+ this.withdrawAddressCount = withdrawAddressCount;
+ }
+
+ /**
+ * 获取去重交易地址数量
+ *
+ * @return tx_address_count - 去重交易地址数量
+ */
+ public Integer getTxAddressCount() {
+ return txAddressCount;
+ }
+
+ /**
+ * 设置去重交易地址数量
+ *
+ * @param txAddressCount 去重交易地址数量
+ */
+ public void setTxAddressCount(Integer txAddressCount) {
+ this.txAddressCount = txAddressCount;
+ }
+
+ /**
+ * 获取消耗手续费总额
+ *
+ * @return fee_amount - 消耗手续费总额
+ */
+ public BigDecimal getFeeAmount() {
+ return feeAmount;
+ }
+
+ /**
+ * 设置消耗手续费总额
+ *
+ * @param feeAmount 消耗手续费总额
+ */
+ public void setFeeAmount(BigDecimal feeAmount) {
+ this.feeAmount = feeAmount;
+ }
+
+ /**
+ * @return update_time
+ */
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+
+ /**
+ * @param updateTime
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+}
\ No newline at end of file
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/TokenPriceDto.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/TokenPriceDto.java
new file mode 100644
index 00000000..66cc0612
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/TokenPriceDto.java
@@ -0,0 +1,50 @@
+package com.github.ontio.model.dto;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.github.ontio.util.TxAmountSerializer;
+import com.github.ontio.util.external.CoinMarketCapQuotes;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author LiuQi
+ */
+@Getter
+@Setter
+public class TokenPriceDto implements Serializable {
+
+ private String token;
+
+ private int rank;
+
+ private Map prices;
+
+ @Getter
+ @RequiredArgsConstructor
+ public static class Price implements Serializable {
+ @JsonSerialize(using = TxAmountSerializer.class)
+ private final BigDecimal price;
+ @JsonSerialize(using = TxAmountSerializer.class)
+ private final BigDecimal percentage;
+ }
+
+ public static TokenPriceDto from(String token, CoinMarketCapQuotes quotes) {
+ TokenPriceDto dto = new TokenPriceDto();
+ dto.setToken(token);
+ dto.setRank(quotes.getRank());
+ Map prices = new HashMap<>();
+ quotes.getQuotes().forEach((fiat, quote) -> {
+ Price price = new Price(quote.getPrice(), quote.getPercentageOneDay());
+ prices.put(fiat, price);
+ });
+ dto.setPrices(prices);
+ return dto;
+ }
+
+}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/AddressAggregationDto.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/AddressAggregationDto.java
new file mode 100644
index 00000000..681f3f2d
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/AddressAggregationDto.java
@@ -0,0 +1,34 @@
+package com.github.ontio.model.dto.aggregation;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.github.ontio.util.TxAmountSerializer;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * @author LiuQi
+ */
+@Getter
+@Setter
+public class AddressAggregationDto extends BaseAggregationDto {
+
+ @JsonSerialize(using = TxAmountSerializer.class)
+ private BigDecimal balance;
+
+ private Integer depositCount;
+
+ private Integer withdrawCount;
+
+ private Integer txCount;
+
+ private Integer depositAddr;
+
+ private Integer withdrawAddr;
+
+ private Integer txAddr;
+
+ private Integer contractCount;
+
+}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/AddressBalanceAggregationsDto.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/AddressBalanceAggregationsDto.java
new file mode 100644
index 00000000..7d390330
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/AddressBalanceAggregationsDto.java
@@ -0,0 +1,22 @@
+package com.github.ontio.model.dto.aggregation;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author LiuQi
+ */
+@RequiredArgsConstructor
+@Getter
+public class AddressBalanceAggregationsDto implements Serializable {
+
+ private final ExtremeBalanceDto max;
+
+ private final ExtremeBalanceDto min;
+
+ private final List records;
+
+}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/BaseAggregationDto.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/BaseAggregationDto.java
new file mode 100644
index 00000000..6b97148d
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/BaseAggregationDto.java
@@ -0,0 +1,21 @@
+package com.github.ontio.model.dto.aggregation;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * @author LiuQi
+ */
+@Getter
+@Setter
+public abstract class BaseAggregationDto implements Serializable {
+
+ private String date;
+
+ public String getDate() {
+ return date.replaceAll("-", "");
+ }
+
+}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/ContractAggregationDto.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/ContractAggregationDto.java
new file mode 100644
index 00000000..62533f2d
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/ContractAggregationDto.java
@@ -0,0 +1,30 @@
+package com.github.ontio.model.dto.aggregation;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.github.ontio.util.TxAmountSerializer;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * @author LiuQi
+ */
+@Getter
+@Setter
+public class ContractAggregationDto extends BaseAggregationDto {
+
+ @JsonSerialize(using = TxAmountSerializer.class)
+ private BigDecimal txAmount;
+
+ private Integer txCount;
+
+ private Integer depositAddr;
+
+ private Integer withdrawAddr;
+
+ private Integer txAddr;
+
+ private Integer contractCount;
+
+}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/ExtremeBalanceDto.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/ExtremeBalanceDto.java
new file mode 100644
index 00000000..e56576e9
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/ExtremeBalanceDto.java
@@ -0,0 +1,20 @@
+package com.github.ontio.model.dto.aggregation;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.github.ontio.util.TxAmountSerializer;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * @author LiuQi
+ */
+@Getter
+@Setter
+public class ExtremeBalanceDto extends BaseAggregationDto {
+
+ @JsonSerialize(using = TxAmountSerializer.class)
+ private BigDecimal balance;
+
+}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/TokenAggregationDto.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/TokenAggregationDto.java
new file mode 100644
index 00000000..bb65276b
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/aggregation/TokenAggregationDto.java
@@ -0,0 +1,28 @@
+package com.github.ontio.model.dto.aggregation;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.github.ontio.util.TxAmountSerializer;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * @author LiuQi
+ */
+@Getter
+@Setter
+public class TokenAggregationDto extends BaseAggregationDto {
+
+ private Integer txCount;
+
+ @JsonSerialize(using = TxAmountSerializer.class)
+ private BigDecimal txAmount;
+
+ private Integer depositAddr;
+
+ private Integer withdrawAddr;
+
+ private Integer txAddr;
+
+}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/ranking/AddressRankingDto.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/ranking/AddressRankingDto.java
new file mode 100644
index 00000000..5aba67f6
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/ranking/AddressRankingDto.java
@@ -0,0 +1,15 @@
+package com.github.ontio.model.dto.ranking;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author LiuQi
+ */
+@Getter
+@Setter
+public class AddressRankingDto extends BaseRankingDto {
+
+ private String address;
+
+}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/ranking/BaseRankingDto.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/ranking/BaseRankingDto.java
new file mode 100644
index 00000000..d0efdf68
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/ranking/BaseRankingDto.java
@@ -0,0 +1,30 @@
+package com.github.ontio.model.dto.ranking;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.github.ontio.util.TxAmountSerializer;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @author LiuQi
+ */
+@Getter
+@Setter
+public abstract class BaseRankingDto implements Serializable {
+
+ @JsonIgnore
+ private short rankingId;
+
+ private short ranking;
+
+ @JsonSerialize(using = TxAmountSerializer.class)
+ private BigDecimal amount;
+
+ @JsonSerialize(using = TxAmountSerializer.class)
+ private BigDecimal percentage;
+
+}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/ranking/TokenRankingDto.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/ranking/TokenRankingDto.java
new file mode 100644
index 00000000..76040665
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/model/dto/ranking/TokenRankingDto.java
@@ -0,0 +1,19 @@
+package com.github.ontio.model.dto.ranking;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author LiuQi
+ */
+@Getter
+@Setter
+public class TokenRankingDto extends BaseRankingDto {
+
+ private String contractHash;
+
+ private String tokenName;
+
+ private String logo;
+
+}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/service/IAddressService.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/service/IAddressService.java
index 6db1ca92..eb302bc1 100644
--- a/back-end-projects/Explorer/src/main/java/com/github/ontio/service/IAddressService.java
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/service/IAddressService.java
@@ -2,6 +2,9 @@
import com.github.ontio.model.common.ResponseBean;
+import java.util.Date;
+import java.util.List;
+
public interface IAddressService {
ResponseBean queryAddressBalance(String address, String tokenType);
@@ -18,6 +21,13 @@ public interface IAddressService {
ResponseBean queryTransferTxsByTime4Onto(String address, String assetName, Long beginTime, Long endTime, String addressType);
- ResponseBean queryTransferTxsByTimeAndPage4Onto(String address, String assetName, Long endTime, Integer pageSize, String addressType);
+ ResponseBean queryTransferTxsByTimeAndPage4Onto(String address, String assetName, Long endTime, Integer pageSize,
+ String addressType);
+
+ ResponseBean queryDailyAggregation(String address, String token, Date from, Date to);
+
+ ResponseBean queryDailyAggregationOfTokenType(String address, String tokenType, Date from, Date to);
+
+ ResponseBean queryRankings(List rankingIds, short duration);
}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/service/IContractService.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/service/IContractService.java
index 301485d6..b1edee4f 100644
--- a/back-end-projects/Explorer/src/main/java/com/github/ontio/service/IContractService.java
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/service/IContractService.java
@@ -20,6 +20,8 @@
import com.github.ontio.model.common.ResponseBean;
+import java.util.Date;
+
public interface IContractService {
ResponseBean queryContractsByPage(Integer pagesize, Integer pageNum);
@@ -40,4 +42,8 @@ public interface IContractService {
ResponseBean queryDappstoreDappsSummary();
+ ResponseBean queryDailyAggregation(String contractHash, String token, Date from, Date to);
+
+ ResponseBean queryDailyAggregationOfTokenType(String contractHash, String tokenType, Date from, Date to);
+
}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/service/ITokenService.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/service/ITokenService.java
index 182ab85f..40bbc5a3 100644
--- a/back-end-projects/Explorer/src/main/java/com/github/ontio/service/ITokenService.java
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/service/ITokenService.java
@@ -2,6 +2,9 @@
import com.github.ontio.model.common.ResponseBean;
+import java.util.Date;
+import java.util.List;
+
/**
* @author zhouq
* @version 1.0
@@ -15,5 +18,10 @@ public interface ITokenService {
ResponseBean queryOep8TxsByPage(String contractHash, String tokenName, Integer pageNumber, Integer pageSize);
+ ResponseBean queryDailyAggregations(String tokenType, String contractHash, Date from, Date to);
+
+ ResponseBean queryRankings(List rankingIds, short duration);
+
+ ResponseBean queryPrice(String token, String fiat);
}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/service/impl/AddressServiceImpl.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/service/impl/AddressServiceImpl.java
index 0454cdf5..606b08c9 100644
--- a/back-end-projects/Explorer/src/main/java/com/github/ontio/service/impl/AddressServiceImpl.java
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/service/impl/AddressServiceImpl.java
@@ -2,10 +2,15 @@
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.Expiry;
import com.github.ontio.config.ParamsConfig;
+import com.github.ontio.mapper.AddressDailyAggregationMapper;
import com.github.ontio.mapper.Oep4Mapper;
import com.github.ontio.mapper.Oep5Mapper;
import com.github.ontio.mapper.Oep8Mapper;
+import com.github.ontio.mapper.RankingMapper;
import com.github.ontio.mapper.TxDetailMapper;
import com.github.ontio.model.common.ResponseBean;
import com.github.ontio.model.dao.Oep4;
@@ -15,6 +20,10 @@
import com.github.ontio.model.dto.QueryBatchBalanceDto;
import com.github.ontio.model.dto.TransferTxDetailDto;
import com.github.ontio.model.dto.TransferTxDto;
+import com.github.ontio.model.dto.aggregation.AddressAggregationDto;
+import com.github.ontio.model.dto.aggregation.AddressBalanceAggregationsDto;
+import com.github.ontio.model.dto.aggregation.ExtremeBalanceDto;
+import com.github.ontio.model.dto.ranking.AddressRankingDto;
import com.github.ontio.service.IAddressService;
import com.github.ontio.util.ConstantParam;
import com.github.ontio.util.ErrorInfo;
@@ -22,14 +31,18 @@
import com.github.ontio.util.JacksonUtil;
import com.github.ontio.util.OntologySDKService;
import lombok.extern.slf4j.Slf4j;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
+import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
/**
* @author zhouq
@@ -50,15 +63,21 @@ public class AddressServiceImpl implements IAddressService {
private final TxDetailMapper txDetailMapper;
private final ParamsConfig paramsConfig;
private final CommonService commonService;
+ private final AddressDailyAggregationMapper addressDailyAggregationMapper;
+ private final RankingMapper rankingMapper;
@Autowired
- public AddressServiceImpl(Oep4Mapper oep4Mapper, Oep8Mapper oep8Mapper, Oep5Mapper oep5Mapper, TxDetailMapper txDetailMapper, ParamsConfig paramsConfig, CommonService commonService) {
+ public AddressServiceImpl(Oep4Mapper oep4Mapper, Oep8Mapper oep8Mapper, Oep5Mapper oep5Mapper, TxDetailMapper txDetailMapper,
+ ParamsConfig paramsConfig, CommonService commonService, AddressDailyAggregationMapper addressDailyAggregationMapper,
+ RankingMapper rankingMapper) {
this.oep4Mapper = oep4Mapper;
this.oep8Mapper = oep8Mapper;
this.oep5Mapper = oep5Mapper;
this.txDetailMapper = txDetailMapper;
this.paramsConfig = paramsConfig;
this.commonService = commonService;
+ this.addressDailyAggregationMapper = addressDailyAggregationMapper;
+ this.rankingMapper = rankingMapper;
}
private OntologySDKService sdk;
@@ -476,9 +495,11 @@ private List getOep4BalanceOld(String address, String assetName) {
String contractHash = oep4.getContractHash();
String vmCategory = oep4.getVmCategory();
if (ConstantParam.VM_CATEGORY_NEOVM.equals(vmCategory)) {
- balance = new BigDecimal(sdk.getNeovmOep4AssetBalance(address, contractHash)).divide(new BigDecimal(Math.pow(10, oep4.getDecimals())));
+ balance = new BigDecimal(sdk.getNeovmOep4AssetBalance(address, contractHash)).divide(new BigDecimal(Math.pow(10,
+ oep4.getDecimals())));
} else if (ConstantParam.VM_CATEGORY_WASMVM.equals(vmCategory)) {
- balance = new BigDecimal(sdk.getWasmvmOep4AssetBalance(address, contractHash)).divide(new BigDecimal(Math.pow(10, oep4.getDecimals())));
+ balance = new BigDecimal(sdk.getWasmvmOep4AssetBalance(address, contractHash)).divide(new BigDecimal(Math.pow(10,
+ oep4.getDecimals())));
}
if (balance.compareTo(ConstantParam.ZERO) == 0) {
continue;
@@ -509,9 +530,11 @@ private List getOep4Balance2(String address, Oep4 oep4) {
String vmCategory = oep4.getVmCategory();
BigDecimal balance = new BigDecimal("0");
if (ConstantParam.VM_CATEGORY_NEOVM.equals(vmCategory)) {
- balance = new BigDecimal(sdk.getNeovmOep4AssetBalance(address, contractHash)).divide(new BigDecimal(Math.pow(10, oep4.getDecimals())));
+ balance = new BigDecimal(sdk.getNeovmOep4AssetBalance(address, contractHash)).divide(new BigDecimal(Math.pow(10,
+ oep4.getDecimals())));
} else if (ConstantParam.VM_CATEGORY_WASMVM.equals(vmCategory)) {
- balance = new BigDecimal(sdk.getWasmvmOep4AssetBalance(address, contractHash)).divide(new BigDecimal(Math.pow(10, oep4.getDecimals())));
+ balance = new BigDecimal(sdk.getWasmvmOep4AssetBalance(address, contractHash)).divide(new BigDecimal(Math.pow(10,
+ oep4.getDecimals())));
}
BalanceDto balanceDto = BalanceDto.builder()
.assetName(oep4.getSymbol())
@@ -665,8 +688,9 @@ private List getOep4Balance(String address, String assetName) {
.contractAddrs(contractAddrsStr.substring(0, contractAddrsStr.length() - 1))
.build();
- String responseStr = commonService.httpPostRequest(paramsConfig.BALANCESERVICE_HOST + ConstantParam.BALANCESERVICE_QUERYBALANCE_URL,
- JacksonUtil.beanToJSonStr(queryBatchBalanceDto), null);
+ String responseStr =
+ commonService.httpPostRequest(paramsConfig.BALANCESERVICE_HOST + ConstantParam.BALANCESERVICE_QUERYBALANCE_URL,
+ JacksonUtil.beanToJSonStr(queryBatchBalanceDto), null);
if (Helper.isNotEmptyAndNull(responseStr)) {
JSONObject jsonObject = JSONObject.parseObject(responseStr);
JSONArray oepBalanceArray = ((JSONObject) jsonObject.getJSONArray("Result").get(0)).getJSONArray("OepBalance");
@@ -727,8 +751,9 @@ private List getOep5Balance(String address, String assetName, String
.contractAddrs(contractAddrsStr.substring(0, contractAddrsStr.length() - 1))
.build();
- String responseStr = commonService.httpPostRequest(paramsConfig.BALANCESERVICE_HOST + ConstantParam.BALANCESERVICE_QUERYBALANCE_URL,
- JacksonUtil.beanToJSonStr(queryBatchBalanceDto), null);
+ String responseStr =
+ commonService.httpPostRequest(paramsConfig.BALANCESERVICE_HOST + ConstantParam.BALANCESERVICE_QUERYBALANCE_URL,
+ JacksonUtil.beanToJSonStr(queryBatchBalanceDto), null);
if (Helper.isNotEmptyAndNull(responseStr)) {
JSONObject jsonObject = JSONObject.parseObject(responseStr);
JSONArray oepBalanceArray = ((JSONObject) jsonObject.getJSONArray("Result").get(0)).getJSONArray("OepBalance");
@@ -802,8 +827,9 @@ private List getOep8Balance(String address, String assetName) {
.contractAddrs(contractAddrsStr.substring(0, contractAddrsStr.length() - 1))
.build();
- String responseStr = commonService.httpPostRequest(paramsConfig.BALANCESERVICE_HOST + ConstantParam.BALANCESERVICE_QUERYBALANCE_URL,
- JacksonUtil.beanToJSonStr(queryBatchBalanceDto), null);
+ String responseStr =
+ commonService.httpPostRequest(paramsConfig.BALANCESERVICE_HOST + ConstantParam.BALANCESERVICE_QUERYBALANCE_URL,
+ JacksonUtil.beanToJSonStr(queryBatchBalanceDto), null);
if (Helper.isNotEmptyAndNull(responseStr)) {
JSONObject jsonObject = JSONObject.parseObject(responseStr);
JSONArray oepBalanceArray = ((JSONObject) jsonObject.getJSONArray("Result").get(0)).getJSONArray("OepBalance");
@@ -869,8 +895,9 @@ private List getOep8Balance4Onto(String address, String assetName) {
.contractAddrs(contractAddrsStr.substring(0, contractAddrsStr.length() - 1))
.build();
- String responseStr = commonService.httpPostRequest(paramsConfig.BALANCESERVICE_HOST + ConstantParam.BALANCESERVICE_QUERYBALANCE_URL,
- JacksonUtil.beanToJSonStr(queryBatchBalanceDto), null);
+ String responseStr =
+ commonService.httpPostRequest(paramsConfig.BALANCESERVICE_HOST + ConstantParam.BALANCESERVICE_QUERYBALANCE_URL,
+ JacksonUtil.beanToJSonStr(queryBatchBalanceDto), null);
if (Helper.isNotEmptyAndNull(responseStr)) {
JSONObject jsonObject = JSONObject.parseObject(responseStr);
JSONArray oepBalanceArray = ((JSONObject) jsonObject.getJSONArray("Result").get(0)).getJSONArray("OepBalance");
@@ -1009,11 +1036,14 @@ private String calculateWaitingBoundOng(String address, String ont) {
BigDecimal totalOng = new BigDecimal("0");
//before 20190630000000 UTC
if (latestOntTransferTxTime < TIMESTAMP_20190630000000_UTC) {
- BigDecimal ong01 = new BigDecimal(TIMESTAMP_20190630000000_UTC).subtract(new BigDecimal(latestOntTransferTxTime)).multiply(new BigDecimal(5));
- BigDecimal ong02 = new BigDecimal(now).subtract(new BigDecimal(TIMESTAMP_20190630000000_UTC)).multiply(paramsConfig.ONG_SECOND_GENERATE);
+ BigDecimal ong01 =
+ new BigDecimal(TIMESTAMP_20190630000000_UTC).subtract(new BigDecimal(latestOntTransferTxTime)).multiply(new BigDecimal(5));
+ BigDecimal ong02 =
+ new BigDecimal(now).subtract(new BigDecimal(TIMESTAMP_20190630000000_UTC)).multiply(paramsConfig.ONG_SECOND_GENERATE);
totalOng = ong01.add(ong02);
} else {
- totalOng = new BigDecimal(now).subtract(new BigDecimal(latestOntTransferTxTime)).multiply(paramsConfig.ONG_SECOND_GENERATE);
+ totalOng =
+ new BigDecimal(now).subtract(new BigDecimal(latestOntTransferTxTime)).multiply(paramsConfig.ONG_SECOND_GENERATE);
}
BigDecimal ong = totalOng.multiply(new BigDecimal(ont)).divide(ConstantParam.ONT_TOTAL);
@@ -1024,9 +1054,9 @@ private String calculateWaitingBoundOng(String address, String ont) {
@Override
public ResponseBean queryTransferTxsByPage(String address, String assetName, Integer pageNumber, Integer pageSize) {
- int start = pageSize * (pageNumber - 1) < 0 ? 0 : pageSize * (pageNumber - 1);
- List transferTxDtos = txDetailMapper.selectTransferTxsByPage(address, assetName, start, pageSize);
- transferTxDtos = formatTransferTxDtos(transferTxDtos);
+ int start = pageSize * (pageNumber - 1) < 0 ? 0 : pageSize * (pageNumber - 1);
+ List transferTxDtos = txDetailMapper.selectTransferTxsByPage(address, assetName, start, pageSize);
+ transferTxDtos = formatTransferTxDtos(transferTxDtos);
return new ResponseBean(ErrorInfo.SUCCESS.code(), ErrorInfo.SUCCESS.desc(), transferTxDtos);
}
@@ -1039,9 +1069,11 @@ public ResponseBean queryTransferTxsByPage(String address, String assetName, Int
* @param formattedTransferTxDtos
* @return
*/
- private List getTransferTxDtosByPage(int pageNumber, int pageSize, List formattedTransferTxDtos) {
+ private List getTransferTxDtosByPage(int pageNumber, int pageSize,
+ List formattedTransferTxDtos) {
- int start = (pageNumber - 1) * pageSize > formattedTransferTxDtos.size() ? formattedTransferTxDtos.size() : (pageNumber - 1) * pageSize;
+ int start = (pageNumber - 1) * pageSize > formattedTransferTxDtos.size() ? formattedTransferTxDtos.size() :
+ (pageNumber - 1) * pageSize;
int end = (pageSize + start) > formattedTransferTxDtos.size() ? formattedTransferTxDtos.size() : (pageSize + start);
return formattedTransferTxDtos.subList(start, end);
@@ -1056,7 +1088,8 @@ public ResponseBean queryTransferTxsByTime(String address, String assetName, Lon
}
@Override
- public ResponseBean queryTransferTxsByTime4Onto(String address, String assetName, Long beginTime, Long endTime, String addressType) {
+ public ResponseBean queryTransferTxsByTime4Onto(String address, String assetName, Long beginTime, Long endTime,
+ String addressType) {
List transferTxDtos = new ArrayList<>();
@@ -1073,7 +1106,8 @@ public ResponseBean queryTransferTxsByTime4Onto(String address, String assetName
//dragon asset use 'like' query, for ONTO
if (ConstantParam.HYPERDRAGONS.equals(assetName)) {
assetName = assetName + "%";
- transferTxDtos = txDetailMapper.selectDragonTransferTxsByTimeInFromAddr4Onto(address, assetName, beginTime, endTime);
+ transferTxDtos = txDetailMapper.selectDragonTransferTxsByTimeInFromAddr4Onto(address, assetName, beginTime,
+ endTime);
} else {
transferTxDtos = txDetailMapper.selectTransferTxsByTimeInFromAddr4Onto(address, assetName, beginTime, endTime);
}
@@ -1093,7 +1127,8 @@ public ResponseBean queryTransferTxsByTime4Onto(String address, String assetName
}
@Override
- public ResponseBean queryTransferTxsByTimeAndPage4Onto(String address, String assetName, Long endTime, Integer pageSize, String addressType) {
+ public ResponseBean queryTransferTxsByTimeAndPage4Onto(String address, String assetName, Long endTime, Integer pageSize,
+ String addressType) {
List transferTxDtos = new ArrayList<>();
@@ -1110,16 +1145,19 @@ public ResponseBean queryTransferTxsByTimeAndPage4Onto(String address, String as
//dragon asset use 'like' query, for ONTO
if (ConstantParam.HYPERDRAGONS.equals(assetName)) {
assetName = assetName + "%";
- transferTxDtos = txDetailMapper.selectDragonTransferTxsByTimeAndPageInFromAddr4Onto(address, assetName, endTime, pageSize);
+ transferTxDtos = txDetailMapper.selectDragonTransferTxsByTimeAndPageInFromAddr4Onto(address, assetName, endTime,
+ pageSize);
} else {
- transferTxDtos = txDetailMapper.selectTransferTxsByTimeAndPageInFromAddr4Onto(address, assetName, endTime, pageSize);
+ transferTxDtos = txDetailMapper.selectTransferTxsByTimeAndPageInFromAddr4Onto(address, assetName, endTime,
+ pageSize);
}
} else if (ADDRESS_TYPE_TO.equals(addressType)) {
//query transfer txs by toaddress
//dragon asset use 'like' query, for ONTO
if (ConstantParam.HYPERDRAGONS.equals(assetName)) {
assetName = assetName + "%";
- transferTxDtos = txDetailMapper.selectDragonTransferTxsByTimeAndPageInToAddr4Onto(address, assetName, endTime, pageSize);
+ transferTxDtos = txDetailMapper.selectDragonTransferTxsByTimeAndPageInToAddr4Onto(address, assetName, endTime,
+ pageSize);
} else {
transferTxDtos = txDetailMapper.selectTransferTxsByTimeAndPageInToAddr4Onto(address, assetName, endTime, pageSize);
}
@@ -1129,6 +1167,57 @@ public ResponseBean queryTransferTxsByTimeAndPage4Onto(String address, String as
return new ResponseBean(ErrorInfo.SUCCESS.code(), ErrorInfo.SUCCESS.desc(), formattedTransferTxDtos);
}
+ private Cache extremeBalances = Caffeine.newBuilder()
+ .expireAfter(new Expiry() {
+ @Override
+ public long expireAfterCreate(String key, ExtremeBalanceDto value, long currentTime) {
+ DateTime now = DateTime.now(DateTimeZone.UTC);
+ return (now.plusDays(1).withTime(0, 5, 0, 0).getMillis() - System.currentTimeMillis()) * 1000000;
+ }
+
+ @Override
+ public long expireAfterUpdate(String key, ExtremeBalanceDto value, long currentTime,
+ long currentDuration) {
+ return currentDuration;
+ }
+
+ @Override
+ public long expireAfterRead(String key, ExtremeBalanceDto value, long currentTime,
+ long currentDuration) {
+ return currentDuration;
+ }
+ }
+ ).maximumSize(0).build(); // TODO disable cache temporarily
+
+ @Override
+ public ResponseBean queryDailyAggregation(String address, String token, Date from, Date to) {
+ String tokenContractHash = paramsConfig.getContractHash(token);
+ List aggregations = addressDailyAggregationMapper.findAggregations(address, tokenContractHash,
+ from, to);
+ ExtremeBalanceDto max = extremeBalances.get(address + tokenContractHash + "max",
+ key -> addressDailyAggregationMapper.findMaxBalance(address, tokenContractHash));
+ ExtremeBalanceDto min = extremeBalances.get(address + token + "min",
+ key -> addressDailyAggregationMapper.findMinBalance(address, tokenContractHash));
+ AddressBalanceAggregationsDto result = new AddressBalanceAggregationsDto(max, min, aggregations);
+ return new ResponseBean(ErrorInfo.SUCCESS.code(), ErrorInfo.SUCCESS.desc(), result);
+ }
+
+ @Override
+ public ResponseBean queryDailyAggregationOfTokenType(String address, String tokenType, Date from, Date to) {
+ String tokenContractHash = paramsConfig.getContractHash(tokenType);
+ List aggregations = addressDailyAggregationMapper.findAggregationsForToken(address,
+ tokenContractHash, from, to);
+ return new ResponseBean(ErrorInfo.SUCCESS.code(), ErrorInfo.SUCCESS.desc(), aggregations);
+ }
+
+ @Override
+ public ResponseBean queryRankings(List rankingIds, short duration) {
+ List rankings = rankingMapper.findAddressRankings(rankingIds, duration);
+ Map> rankingMap =
+ rankings.stream().collect(Collectors.groupingBy(AddressRankingDto::getRankingId));
+ return new ResponseBean(ErrorInfo.SUCCESS.code(), ErrorInfo.SUCCESS.desc(), rankingMap);
+ }
+
/**
* 格式化转账交易列表
*
@@ -1162,7 +1251,8 @@ private List formatTransferTxDtos(List transferTxD
.contractHash(transferTxDto.getContractHash())
.build();
- List transferTxnList = (List) (formattedTransferTxs.get(formattedTransferTxs.size() - 1)).getTransfers();
+ List transferTxnList =
+ (List) (formattedTransferTxs.get(formattedTransferTxs.size() - 1)).getTransfers();
transferTxnList.add(transferTxDetailDto);
}
previousTxIndex = transferTxDto.getTxIndex();
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/service/impl/ContractServiceImpl.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/service/impl/ContractServiceImpl.java
index 46c5bdf6..cfe9df50 100644
--- a/back-end-projects/Explorer/src/main/java/com/github/ontio/service/impl/ContractServiceImpl.java
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/service/impl/ContractServiceImpl.java
@@ -21,12 +21,25 @@
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.ontio.config.ParamsConfig;
-import com.github.ontio.mapper.*;
+import com.github.ontio.mapper.ContractDailyAggregationMapper;
+import com.github.ontio.mapper.ContractDailySummaryMapper;
+import com.github.ontio.mapper.ContractMapper;
+import com.github.ontio.mapper.NodeInfoOffChainMapper;
+import com.github.ontio.mapper.NodeInfoOnChainMapper;
+import com.github.ontio.mapper.Oep4TxDetailMapper;
+import com.github.ontio.mapper.Oep5TxDetailMapper;
+import com.github.ontio.mapper.Oep8TxDetailMapper;
+import com.github.ontio.mapper.TxEventLogMapper;
import com.github.ontio.model.common.PageResponseBean;
import com.github.ontio.model.common.ResponseBean;
import com.github.ontio.model.dao.NodeInfoOffChain;
import com.github.ontio.model.dao.NodeInfoOnChain;
-import com.github.ontio.model.dto.*;
+import com.github.ontio.model.dto.ContractDto;
+import com.github.ontio.model.dto.NodeInfoOffChainDto;
+import com.github.ontio.model.dto.Oep5TxDetailDto;
+import com.github.ontio.model.dto.TxDetailDto;
+import com.github.ontio.model.dto.TxEventLogDto;
+import com.github.ontio.model.dto.aggregation.ContractAggregationDto;
import com.github.ontio.service.IContractService;
import com.github.ontio.util.ConstantParam;
import com.github.ontio.util.ErrorInfo;
@@ -38,7 +51,15 @@
import tk.mybatis.mapper.entity.Example;
import java.math.BigDecimal;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
@Slf4j
@Service("ContractService")
@@ -53,9 +74,14 @@ public class ContractServiceImpl implements IContractService {
private final ParamsConfig paramsConfig;
private final NodeInfoOffChainMapper nodeInfoOffChainMapper;
private final NodeInfoOnChainMapper nodeInfoOnChainMapper;
+ private final ContractDailyAggregationMapper contractDailyAggregationMapper;
@Autowired
- public ContractServiceImpl(ContractMapper contractMapper, Oep4TxDetailMapper oep4TxDetailMapper, Oep5TxDetailMapper oep5TxDetailMapper, Oep8TxDetailMapper oep8TxDetailMapper, TxEventLogMapper txEventLogMapper, ParamsConfig paramsConfig, NodeInfoOffChainMapper nodeInfoOffChainMapper, ContractDailySummaryMapper contractDailySummaryMapper, NodeInfoOnChainMapper nodeInfoOnChainMapper) {
+ public ContractServiceImpl(ContractMapper contractMapper, Oep4TxDetailMapper oep4TxDetailMapper,
+ Oep5TxDetailMapper oep5TxDetailMapper, Oep8TxDetailMapper oep8TxDetailMapper, TxEventLogMapper txEventLogMapper,
+ ParamsConfig paramsConfig, NodeInfoOffChainMapper nodeInfoOffChainMapper,
+ ContractDailySummaryMapper contractDailySummaryMapper, NodeInfoOnChainMapper nodeInfoOnChainMapper,
+ ContractDailyAggregationMapper contractDailyAggregationMapper) {
this.contractMapper = contractMapper;
this.oep4TxDetailMapper = oep4TxDetailMapper;
this.oep5TxDetailMapper = oep5TxDetailMapper;
@@ -65,6 +91,7 @@ public ContractServiceImpl(ContractMapper contractMapper, Oep4TxDetailMapper oep
this.nodeInfoOffChainMapper = nodeInfoOffChainMapper;
this.contractDailySummaryMapper = contractDailySummaryMapper;
this.nodeInfoOnChainMapper = nodeInfoOnChainMapper;
+ this.contractDailyAggregationMapper = contractDailyAggregationMapper;
}
private OntologySDKService sdk;
@@ -571,14 +598,32 @@ public ResponseBean queryDappstoreDappsSummary() {
rsMap.put("day_activeaddress_count", 0);
rsMap.put("day_tx_count", 0);
} else {
- contractInfo.put("day_ont_sum", ((BigDecimal) contractInfo.get("day_ont_sum")).stripTrailingZeros().toPlainString());
- contractInfo.put("day_ong_sum", ((BigDecimal) contractInfo.get("day_ong_sum")).stripTrailingZeros().toPlainString());
+ contractInfo.put("day_ont_sum",
+ ((BigDecimal) contractInfo.get("day_ont_sum")).stripTrailingZeros().toPlainString());
+ contractInfo.put("day_ong_sum",
+ ((BigDecimal) contractInfo.get("day_ong_sum")).stripTrailingZeros().toPlainString());
rsMap.putAll(contractInfo);
}
}
return new ResponseBean(ErrorInfo.SUCCESS.code(), ErrorInfo.SUCCESS.desc(), rsMap);
}
+ @Override
+ public ResponseBean queryDailyAggregation(String contractHash, String token, Date from, Date to) {
+ String tokenContractHash = paramsConfig.getContractHash(token);
+ List aggregations = contractDailyAggregationMapper.findAggregations(contractHash, tokenContractHash,
+ from, to);
+ return new ResponseBean(ErrorInfo.SUCCESS.code(), ErrorInfo.SUCCESS.desc(), aggregations);
+ }
+
+ @Override
+ public ResponseBean queryDailyAggregationOfTokenType(String contractHash, String tokenType, Date from, Date to) {
+ String tokenContractHash = paramsConfig.getContractHash(tokenType);
+ List aggregations = contractDailyAggregationMapper.findAggregationsForToken(contractHash,
+ tokenContractHash, from, to);
+ return new ResponseBean(ErrorInfo.SUCCESS.code(), ErrorInfo.SUCCESS.desc(), aggregations);
+ }
+
private long getDaysAgo0HourTimestamp(int days) {
Calendar calendar = Calendar.getInstance();
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/service/impl/TokenServiceImpl.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/service/impl/TokenServiceImpl.java
index 55f35e13..8c44eda2 100644
--- a/back-end-projects/Explorer/src/main/java/com/github/ontio/service/impl/TokenServiceImpl.java
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/service/impl/TokenServiceImpl.java
@@ -1,27 +1,41 @@
package com.github.ontio.service.impl;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.LoadingCache;
import com.github.ontio.config.ParamsConfig;
-import com.github.ontio.exception.ExplorerException;
-import com.github.ontio.mapper.*;
+import com.github.ontio.mapper.Oep4Mapper;
+import com.github.ontio.mapper.Oep5Mapper;
+import com.github.ontio.mapper.Oep8Mapper;
+import com.github.ontio.mapper.Oep8TxDetailMapper;
+import com.github.ontio.mapper.RankingMapper;
+import com.github.ontio.mapper.TokenDailyAggregationMapper;
import com.github.ontio.model.common.PageResponseBean;
import com.github.ontio.model.common.ResponseBean;
-import com.github.ontio.model.dao.Oep4;
-import com.github.ontio.model.dao.Oep5;
-import com.github.ontio.model.dao.Oep8;
-import com.github.ontio.model.dto.*;
+import com.github.ontio.model.dto.Oep4DetailDto;
+import com.github.ontio.model.dto.Oep5DetailDto;
+import com.github.ontio.model.dto.Oep8DetailDto;
+import com.github.ontio.model.dto.TokenPriceDto;
+import com.github.ontio.model.dto.TxDetailDto;
+import com.github.ontio.model.dto.ranking.TokenRankingDto;
import com.github.ontio.service.ITokenService;
import com.github.ontio.util.ConstantParam;
import com.github.ontio.util.ErrorInfo;
import com.github.ontio.util.Helper;
+import com.github.ontio.util.external.CoinMarketCapApi;
+import com.github.ontio.util.external.CoinMarketCapQuotes;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import java.math.BigDecimal;
-import java.util.*;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
/**
* @author zhouq
@@ -36,13 +50,21 @@ public class TokenServiceImpl implements ITokenService {
private final Oep5Mapper oep5Mapper;
private final Oep8Mapper oep8Mapper;
private final Oep8TxDetailMapper oep8TxDetailMapper;
+ private final TokenDailyAggregationMapper tokenDailyAggregationMapper;
+ private final RankingMapper rankingMapper;
+ private final CoinMarketCapApi coinMarketCapApi;
@Autowired
- public TokenServiceImpl(Oep4Mapper oep4Mapper, Oep5Mapper oep5Mapper, Oep8Mapper oep8Mapper, Oep8TxDetailMapper oep8TxDetailMapper) {
+ public TokenServiceImpl(Oep4Mapper oep4Mapper, Oep5Mapper oep5Mapper, Oep8Mapper oep8Mapper,
+ Oep8TxDetailMapper oep8TxDetailMapper, TokenDailyAggregationMapper tokenDailyAggregationMapper,
+ RankingMapper rankingMapper, CoinMarketCapApi coinMarketCapApi) {
this.oep4Mapper = oep4Mapper;
this.oep5Mapper = oep5Mapper;
this.oep8Mapper = oep8Mapper;
this.oep8TxDetailMapper = oep8TxDetailMapper;
+ this.tokenDailyAggregationMapper = tokenDailyAggregationMapper;
+ this.rankingMapper = rankingMapper;
+ this.coinMarketCapApi = coinMarketCapApi;
}
@Override
@@ -149,7 +171,8 @@ public ResponseBean queryOep8TxsByPage(String contractHash, String tokenName, In
int start = pageSize * (pageNumber - 1) < 0 ? 0 : pageSize * (pageNumber - 1);
- List txDetailDtos = oep8TxDetailMapper.selectTxsByCalledContractHashAndTokenName(contractHash, tokenName, start, pageSize);
+ List txDetailDtos = oep8TxDetailMapper.selectTxsByCalledContractHashAndTokenName(contractHash, tokenName,
+ start, pageSize);
Integer count = oep8TxDetailMapper.selectCountByCalledContracthashAndTokenName(contractHash, tokenName);
PageResponseBean pageResponseBean = new PageResponseBean(txDetailDtos, count);
@@ -157,7 +180,44 @@ public ResponseBean queryOep8TxsByPage(String contractHash, String tokenName, In
return new ResponseBean(ErrorInfo.SUCCESS.code(), ErrorInfo.SUCCESS.desc(), pageResponseBean);
}
+ @Override
+ public ResponseBean queryDailyAggregations(String tokenType, String contractHash, Date from, Date to) {
+ Object result = null;
+ if (ConstantParam.ASSET_TYPE_OEP4.equalsIgnoreCase(tokenType)) {
+ result = tokenDailyAggregationMapper.findAggregations(contractHash, from, to);
+ }
+ return new ResponseBean(ErrorInfo.SUCCESS.code(), ErrorInfo.SUCCESS.desc(), result);
+ }
+
+ @Override
+ public ResponseBean queryRankings(List rankingIds, short duration) {
+ List rankings = rankingMapper.findTokenRankings(rankingIds, duration);
+ Map> rankingMap =
+ rankings.stream().collect(Collectors.groupingBy(TokenRankingDto::getRankingId));
+ return new ResponseBean(ErrorInfo.SUCCESS.code(), ErrorInfo.SUCCESS.desc(), rankingMap);
+ }
+ @Override
+ public ResponseBean queryPrice(String token, String fiat) {
+ String key = token + "-" + fiat;
+ CoinMarketCapQuotes quotes = tokenQuotes.get(key);
+ TokenPriceDto dto = TokenPriceDto.from(token, quotes);
+ return new ResponseBean(ErrorInfo.SUCCESS.code(), ErrorInfo.SUCCESS.desc(), dto);
+ }
+
+ private LoadingCache tokenQuotes;
+ @Autowired
+ public void setParamsConfig(ParamsConfig paramsConfig) {
+ tokenQuotes = Caffeine.newBuilder()
+ .expireAfterWrite(Duration.ofMinutes(paramsConfig.getCoinMarketCapRefreshInterval()))
+ .build(key -> {
+ String[] parts = key.split("-");
+ if (parts.length < 2) {
+ throw new IllegalArgumentException("invalid token-fiat pair: " + key);
+ }
+ return coinMarketCapApi.getQuotes(parts[0], parts[1]);
+ });
+ }
}
diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapApi.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapApi.java
new file mode 100644
index 00000000..423d042f
--- /dev/null
+++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapApi.java
@@ -0,0 +1,51 @@
+package com.github.ontio.util.external;
+
+import retrofit2.Call;
+import retrofit2.http.GET;
+import retrofit2.http.Query;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * @author LiuQi
+ */
+public interface CoinMarketCapApi {
+
+ String ONT_ID = "2566";
+
+ String ONG_ID = "3217";
+
+ @GET("/v1/cryptocurrency/quotes/latest")
+ Call>> getCoinMarketCapQuotes(@Query("id") String id,
+ @Query("convert") String convert);
+
+ default CoinMarketCapQuotes getQuotes(String token, String fiat) throws IOException {
+ String id;
+ switch (token.toUpperCase()) {
+ case "ONT":
+ id = ONT_ID;
+ break;
+ case "ONG":
+ id = ONG_ID;
+ break;
+ default:
+ throw new IllegalArgumentException("unsupported token: " + token);
+ }
+ CoinMarketCapResponse