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> response = + getCoinMarketCapQuotes(id, fiat.toUpperCase()).execute().body(); + if (response == null) { + throw new IOException("cannot get " + fiat + " price of " + token + " from coinMarketCap"); + } + CoinMarketCapStatus status = response.getStatus(); + if (!status.successful()) { + throw new IOException("coinMarketCap api error: " + status.getErrorMessage()); + } + Map quotes = response.getData(); + if (quotes.containsKey(id)) { + return quotes.get(id); + } + throw new IOException("cannot get " + fiat + " price of " + token + " from coinMarketCap"); + } + +} diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapConfiguration.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapConfiguration.java new file mode 100644 index 00000000..cffb15af --- /dev/null +++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapConfiguration.java @@ -0,0 +1,42 @@ +package com.github.ontio.util.external; + +import com.alibaba.fastjson.support.retrofit.Retrofit2ConverterFactory; +import com.github.ontio.config.ParamsConfig; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import retrofit2.Retrofit; + +/** + * @author LiuQi + */ +@Configuration +public class CoinMarketCapConfiguration { + + @Bean + Interceptor coinMarketCapApiInterceptor(ParamsConfig config) { + return chain -> { + Request request = chain.request(); + request = request.newBuilder() + .header("X-CMC_PRO_API_KEY", config.getCoinMarketCapApiKey()) + .header("Accept", "application/json") + .build(); + return chain.proceed(request); + }; + } + + @Bean + CoinMarketCapApi coinMarketCapApi(ParamsConfig config, Interceptor coinMarketCapApiInterceptor) { + OkHttpClient.Builder builder = new OkHttpClient.Builder() + .addInterceptor(coinMarketCapApiInterceptor); + Retrofit retrofit = new Retrofit.Builder() + .baseUrl(config.getCoinMarketCapApiHost()) + .client(builder.build()) + .addConverterFactory(new Retrofit2ConverterFactory()) + .build(); + return retrofit.create(CoinMarketCapApi.class); + } + +} diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapQuote.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapQuote.java new file mode 100644 index 00000000..7f05fa07 --- /dev/null +++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapQuote.java @@ -0,0 +1,28 @@ +package com.github.ontio.util.external; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @author LiuQi + */ +@Getter +@Setter +public class CoinMarketCapQuote implements Serializable { + + private BigDecimal price; + + @JSONField(name = "percent_change_1h") + private BigDecimal percentageOneHour; + + @JSONField(name = "percent_change_24h") + private BigDecimal percentageOneDay; + + @JSONField(name = "percent_change_7d") + private BigDecimal percentageSevenDays; + +} diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapQuotes.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapQuotes.java new file mode 100644 index 00000000..0033a640 --- /dev/null +++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapQuotes.java @@ -0,0 +1,27 @@ +package com.github.ontio.util.external; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Map; + +/** + * @author LiuQi + */ +@Getter +@Setter +public class CoinMarketCapQuotes implements Serializable { + + private String id; + + private String symbol; + + @JSONField(name = "cmc_rank") + private int rank; + + @JSONField(name = "quote") + private Map quotes; + +} diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapResponse.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapResponse.java new file mode 100644 index 00000000..441fd41c --- /dev/null +++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapResponse.java @@ -0,0 +1,19 @@ +package com.github.ontio.util.external; + +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @author LiuQi + */ +@Getter +@Setter +public class CoinMarketCapResponse implements Serializable { + + private T data; + + private CoinMarketCapStatus status; + +} diff --git a/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapStatus.java b/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapStatus.java new file mode 100644 index 00000000..881c8fbc --- /dev/null +++ b/back-end-projects/Explorer/src/main/java/com/github/ontio/util/external/CoinMarketCapStatus.java @@ -0,0 +1,26 @@ +package com.github.ontio.util.external; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @author LiuQi + */ +@Getter +@Setter +public class CoinMarketCapStatus implements Serializable { + + @JSONField(name = "error_code") + private int errorCode; + + @JSONField(name = "error_message") + private String errorMessage; + + public boolean successful() { + return errorCode == 0; + } + +} diff --git a/back-end-projects/Explorer/src/main/resources/db/migration/V1.31__tbl_date.sql b/back-end-projects/Explorer/src/main/resources/db/migration/V1.31__tbl_date.sql new file mode 100644 index 00000000..e89fbeb7 --- /dev/null +++ b/back-end-projects/Explorer/src/main/resources/db/migration/V1.31__tbl_date.sql @@ -0,0 +1,56 @@ +DROP TABLE IF EXISTS numbers_small; +CREATE TABLE numbers_small ( + number INT +); +INSERT INTO numbers_small +VALUES (0), +(1), +(2), +(3), +(4), +(5), +(6), +(7), +(8), +(9); + +DROP TABLE IF EXISTS numbers; +CREATE TABLE numbers ( + number BIGINT +); +INSERT INTO numbers +SELECT thousands.number * 1000 + hundreds.number * 100 + tens.number * 10 + ones.number +FROM numbers_small thousands, numbers_small hundreds, numbers_small tens, numbers_small ones +LIMIT 1000000; + +DROP TABLE IF EXISTS tbl_date; +CREATE TABLE tbl_date ( + id INT PRIMARY KEY, + date DATE NOT NULL COMMENT '实际日期', + year SMALLINT NOT NULL COMMENT '年', + month SMALLINT NOT NULL COMMENT '月份', + day_of_year SMALLINT NOT NULL COMMENT '一年中的第几天', + day_of_month SMALLINT NOT NULL COMMENT '一个月中的第几天', + weekday SMALLINT NOT NULL COMMENT '周几,0 - 6', + week_of_year SMALLINT NOT NULL COMMENT '一年中的第几周', + is_weekend BOOLEAN NOT NULL COMMENT '是否周末', + UNIQUE KEY `idx_date`(`date`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8; + +INSERT INTO tbl_date +SELECT id, + date, + date_format(date, '%Y') AS year, + date_format(date, '%c') AS month, + date_format(date, '%y') AS day_of_year, + date_format(date, '%e') AS day_of_month, + date_format(date, '%w') AS weekday, + date_format(date, '%u') AS week_of_year, + if(date_format(date, '%w') IN (0, 6), TRUE, FALSE) AS is_weekend +FROM (SELECT number + 1 AS id, DATE_ADD('2015-01-01', INTERVAL number DAY) AS date + FROM numbers + WHERE DATE_ADD('2015-01-01', INTERVAL number DAY) BETWEEN '2015-01-01' AND '2999-12-31' + ORDER BY number) d; + +DROP TABLE numbers_small; +DROP TABLE numbers; \ No newline at end of file diff --git a/back-end-projects/Explorer/src/main/resources/db/migration/V1.32__tbl_current.sql b/back-end-projects/Explorer/src/main/resources/db/migration/V1.32__tbl_current.sql new file mode 100644 index 00000000..2fbda5a5 --- /dev/null +++ b/back-end-projects/Explorer/src/main/resources/db/migration/V1.32__tbl_current.sql @@ -0,0 +1,2 @@ +ALTER TABLE tbl_current + ADD COLUMN `last_stat_block_height` INT NOT NULL DEFAULT -1; \ No newline at end of file diff --git a/back-end-projects/Explorer/src/main/resources/db/migration/V1.33__tbl_address_daily_aggregation.sql b/back-end-projects/Explorer/src/main/resources/db/migration/V1.33__tbl_address_daily_aggregation.sql new file mode 100644 index 00000000..895b4955 --- /dev/null +++ b/back-end-projects/Explorer/src/main/resources/db/migration/V1.33__tbl_address_daily_aggregation.sql @@ -0,0 +1,22 @@ +DROP TABLE IF EXISTS tbl_address_daily_aggregation; +CREATE TABLE tbl_address_daily_aggregation ( + address CHAR(80) NOT NULL COMMENT '地址', + token_contract_hash CHAR(40) NOT NULL COMMENT 'Token合约hash', + date_id INT NOT NULL COMMENT '日期维度ID', + balance DECIMAL(40, 9) NOT NULL DEFAULT 0 COMMENT '日终余额', + usd_price DECIMAL(40, 9) NOT NULL DEFAULT 0 COMMENT '当天USD价格', + max_balance DECIMAL(40, 9) NOT NULL DEFAULT 0 COMMENT '最高余额', + min_balance DECIMAL(40, 9) NOT NULL DEFAULT 0 COMMENT '最低余额', + deposit_tx_count INT NOT NULL DEFAULT 0 COMMENT '入金交易数量', + withdraw_tx_count INT NOT NULL DEFAULT 0 COMMENT '出金交易数量', + deposit_amount DECIMAL(40, 9) NOT NULL DEFAULT 0 COMMENT '入金金额', + withdraw_amount DECIMAL(40, 9) NOT NULL DEFAULT 0 COMMENT '出金金额', + deposit_address_count INT NOT NULL DEFAULT 0 COMMENT '去重入金地址数量', + withdraw_address_count INT NOT NULL DEFAULT 0 COMMENT '去重出金地址数量', + tx_address_count INT NOT NULL DEFAULT 0 COMMENT '去重交易地址数量', + fee_amount DECIMAL(40, 9) NOT NULL DEFAULT 0 COMMENT '消耗手续费总额', + contract_count INT NOT NULL DEFAULT 0 COMMENT '调用合约数量,只适用于虚拟Token统计', + is_virtual BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否为虚拟Token统计', + update_time TIMESTAMP NOT NULL DEFAULT now() ON UPDATE now(), + PRIMARY KEY (`address`, `token_contract_hash`, `date_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8; \ No newline at end of file diff --git a/back-end-projects/Explorer/src/main/resources/db/migration/V1.34__tbl_token_daily_aggregation.sql b/back-end-projects/Explorer/src/main/resources/db/migration/V1.34__tbl_token_daily_aggregation.sql new file mode 100644 index 00000000..242d8df9 --- /dev/null +++ b/back-end-projects/Explorer/src/main/resources/db/migration/V1.34__tbl_token_daily_aggregation.sql @@ -0,0 +1,14 @@ +DROP TABLE IF EXISTS tbl_token_daily_aggregation; +CREATE TABLE tbl_token_daily_aggregation ( + token_contract_hash CHAR(40) NOT NULL COMMENT 'Token合约hash', + date_id INT NOT NULL COMMENT '日期维度ID', + usd_price DECIMAL(40, 9) NOT NULL DEFAULT 0 COMMENT '当天USD价格', + tx_count INT NOT NULL DEFAULT 0 COMMENT '交易数量', + tx_amount DECIMAL(40, 9) NOT NULL DEFAULT 0 COMMENT '交易金额', + deposit_address_count INT NOT NULL DEFAULT 0 COMMENT '去重入金地址数量', + withdraw_address_count INT NOT NULL DEFAULT 0 COMMENT '去重出金地址数量', + tx_address_count INT NOT NULL DEFAULT 0 COMMENT '去重交易地址数量', + fee_amount DECIMAL(40, 9) NOT NULL DEFAULT 0 COMMENT '消耗手续费总额', + update_time TIMESTAMP NOT NULL DEFAULT now() ON UPDATE now(), + PRIMARY KEY (`token_contract_hash`, `date_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8; \ No newline at end of file diff --git a/back-end-projects/Explorer/src/main/resources/db/migration/V1.35__tbl_contract_daily_aggregation.sql b/back-end-projects/Explorer/src/main/resources/db/migration/V1.35__tbl_contract_daily_aggregation.sql new file mode 100644 index 00000000..5119242f --- /dev/null +++ b/back-end-projects/Explorer/src/main/resources/db/migration/V1.35__tbl_contract_daily_aggregation.sql @@ -0,0 +1,16 @@ +DROP TABLE IF EXISTS tbl_contract_daily_aggregation; +CREATE TABLE tbl_contract_daily_aggregation ( + contract_hash CHAR(80) NOT NULL COMMENT '合约hash', + token_contract_hash CHAR(40) NOT NULL COMMENT 'Token合约hash', + date_id INT NOT NULL COMMENT '日期维度ID', + tx_count INT NOT NULL DEFAULT 0 COMMENT '交易数量', + tx_amount DECIMAL(40, 9) NOT NULL DEFAULT 0 COMMENT '交易金额', + deposit_address_count INT NOT NULL DEFAULT 0 COMMENT '去重入金交易地址数量', + withdraw_address_count INT NOT NULL DEFAULT 0 COMMENT '去重出金交易地址数量', + tx_address_count INT NOT NULL DEFAULT 0 COMMENT '去重交易地址数量', + fee_amount DECIMAL(40, 9) NOT NULL DEFAULT 0 COMMENT '消耗手续费总额', + contract_count INT NOT NULL DEFAULT 0 COMMENT '调用合约数量,只适用于虚拟Token统计', + is_virtual BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否为虚拟Token统计', + update_time TIMESTAMP NOT NULL DEFAULT now() ON UPDATE now(), + PRIMARY KEY (`contract_hash`, `token_contract_hash`, `date_id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8; \ No newline at end of file diff --git a/back-end-projects/Explorer/src/main/resources/db/migration/V1.36__tbl_ranking.sql b/back-end-projects/Explorer/src/main/resources/db/migration/V1.36__tbl_ranking.sql new file mode 100644 index 00000000..c63f58c5 --- /dev/null +++ b/back-end-projects/Explorer/src/main/resources/db/migration/V1.36__tbl_ranking.sql @@ -0,0 +1,12 @@ +DROP TABLE IF EXISTS tbl_ranking; +CREATE TABLE tbl_ranking ( + ranking_group SMALLINT NOT NULL COMMENT '排名分组,由业务系统决定', + ranking_id SMALLINT NOT NULL COMMENT '具体排名,由业务系统决定', + ranking_duration SMALLINT NOT NULL COMMENT '排名区间,1:24小时;3:3天;7:7天', + ranking SMALLINT NOT NULL COMMENT '排名数,1 - N', + member VARCHAR(80) NOT NULL COMMENT '排名对象,根据不同的排名有不同含义', + amount DECIMAL(40, 9) NOT NULL COMMENT '排名数值', + percentage DECIMAL(4, 2) NOT NULL DEFAULT 0 COMMENT '占比', + update_time TIMESTAMP NOT NULL DEFAULT now() ON UPDATE now(), + PRIMARY KEY (`ranking_group`, `ranking_id`, `ranking_duration`, `ranking`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8; \ No newline at end of file diff --git a/back-end-projects/Explorer/src/main/resources/db/migration/V1.37__tbl_ranking.sql b/back-end-projects/Explorer/src/main/resources/db/migration/V1.37__tbl_ranking.sql new file mode 100644 index 00000000..dddfc762 --- /dev/null +++ b/back-end-projects/Explorer/src/main/resources/db/migration/V1.37__tbl_ranking.sql @@ -0,0 +1,2 @@ +ALTER TABLE tbl_ranking + MODIFY percentage DECIMAL(6, 2) NOT NULL DEFAULT 0; \ No newline at end of file diff --git a/back-end-projects/Explorer/src/main/resources/mapper/AddressDailyAggregationMapper.xml b/back-end-projects/Explorer/src/main/resources/mapper/AddressDailyAggregationMapper.xml new file mode 100644 index 00000000..36888464 --- /dev/null +++ b/back-end-projects/Explorer/src/main/resources/mapper/AddressDailyAggregationMapper.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/back-end-projects/Explorer/src/main/resources/mapper/ContractDailyAggregationMapper.xml b/back-end-projects/Explorer/src/main/resources/mapper/ContractDailyAggregationMapper.xml new file mode 100644 index 00000000..0d4cce98 --- /dev/null +++ b/back-end-projects/Explorer/src/main/resources/mapper/ContractDailyAggregationMapper.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/back-end-projects/Explorer/src/main/resources/mapper/RankingMapper.xml b/back-end-projects/Explorer/src/main/resources/mapper/RankingMapper.xml new file mode 100644 index 00000000..02aa1cf0 --- /dev/null +++ b/back-end-projects/Explorer/src/main/resources/mapper/RankingMapper.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/back-end-projects/Explorer/src/main/resources/mapper/TokenDailyAggregationMapper.xml b/back-end-projects/Explorer/src/main/resources/mapper/TokenDailyAggregationMapper.xml new file mode 100644 index 00000000..48f64656 --- /dev/null +++ b/back-end-projects/Explorer/src/main/resources/mapper/TokenDailyAggregationMapper.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file