diff --git a/src/main/java/com/dl/officialsite/activity/ActivityController.java b/src/main/java/com/dl/officialsite/activity/ActivityController.java index a112b486..aaeec551 100644 --- a/src/main/java/com/dl/officialsite/activity/ActivityController.java +++ b/src/main/java/com/dl/officialsite/activity/ActivityController.java @@ -20,6 +20,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -30,7 +31,9 @@ import javax.servlet.http.HttpSession; import javax.validation.constraints.NotNull; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import static com.dl.officialsite.common.enums.CodeEnums.PARAM_ERROR; @@ -122,7 +125,7 @@ public BaseResponse verifyAndMint(@NotNull @RequestParam("chainId") String chain } /** - * 检查用户是否完成所有任务,如果完成,则生成 NFT mint 签名 + * 检查用户的 Mint 结果 */ @GetMapping("/claim/result") public BaseResponse claimResult(@NotNull @RequestParam("chainId") String chainIdParam, @@ -136,6 +139,28 @@ public BaseResponse claimResult(@NotNull @RequestParam("chainId") String chainId SessionUserInfo sessionUserInfo = HttpSessionUtils.getMember(session); final String address = sessionUserInfo != null ? sessionUserInfo.getAddress() : addressForTesting; - return this.warCraftContractService.rank(address, ContractNameEnum.fromValue(contractName), chainId); + return BaseResponse.successWithData(this.warCraftContractService.rank(address, ContractNameEnum.fromValue(contractName), + chainId).getKey()); + } + + /** + * 检查用户的 Mint 结果 + */ + @GetMapping("/claim/result/v2") + public BaseResponse claimResultWithTokenId(@NotNull @RequestParam("chainId") String chainIdParam, + @RequestParam(required = false) String addressForTesting, + @RequestParam(required = false, defaultValue = "WarCraft") String contractName, + HttpSession session) { + String chainId = Arrays.stream(chainConfig.getIds()).filter(id -> StringUtils.equalsIgnoreCase(chainIdParam, id)) + .findFirst() + .orElseThrow(() -> new BizException(PARAM_ERROR.getCode(), String.format("Chain id %s not exists", chainIdParam))); + + SessionUserInfo sessionUserInfo = HttpSessionUtils.getMember(session); + final String address = sessionUserInfo != null ? sessionUserInfo.getAddress() : addressForTesting; + Pair rank = this.warCraftContractService.rank(address, ContractNameEnum.fromValue(contractName), chainId); + Map result = new HashMap<>(); + result.put("rankId", rank.getKey()); + result.put("tokenId", rank.getValue()); + return BaseResponse.successWithData(result); } } \ No newline at end of file diff --git a/src/main/java/com/dl/officialsite/distributor/DistributeService.java b/src/main/java/com/dl/officialsite/distributor/DistributeService.java index 2f55096e..78f018ff 100644 --- a/src/main/java/com/dl/officialsite/distributor/DistributeService.java +++ b/src/main/java/com/dl/officialsite/distributor/DistributeService.java @@ -24,20 +24,6 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import java.io.IOException; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; -import javax.transaction.Transactional; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpEntity; @@ -60,6 +46,21 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import javax.transaction.Transactional; +import java.io.IOException; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + @Service @Slf4j(topic = "Distribute") @Configuration @@ -228,26 +229,26 @@ private HttpEntity getHttpEntityFromChain(String chainId) throws IOException { HttpPost request = null; switch (chainId) { case Constants.CHAIN_ID_OP: // op - request = new HttpPost("https://api.studio.thegraph.com/query/64403/optimism/version/latest"); + request = new HttpPost("https://gateway-arbitrum.network.thegraph.com/api/18ec3dcb6a75917897da2d5798fb98d3/subgraphs/id/Bfrtk6bLRZoULLzAZ99hZ1Ae8kvFxsUWa4e97XzWJYhG"); break; case Constants.CHAIN_ID_SEPOLIA: // sepolia request = new HttpPost( - "https://api.studio.thegraph.com/query/64403/sepolia/v0.0.12"); + "https://gateway-arbitrum.network.thegraph.com/api/18ec3dcb6a75917897da2d5798fb98d3/subgraphs/id/9p6zFejTBC2bLLJRCdrk1A2PXfZkriRMacM5wiCAyh5Z"); break; case Constants.CHAIN_ID_SCROLL: // scroll - request = new HttpPost("https://api.studio.thegraph.com/query/64403/scroll/version/latest"); + request = new HttpPost("https://gateway-arbitrum.network.thegraph.com/api/18ec3dcb6a75917897da2d5798fb98d3/subgraphs/id/8HhHjdsXrZ1cjq5qNpksoWfAm1NTDDFhH2Yb8ZkBixjo"); break; case Constants.CHAIN_ID_ARBITRUM: // arbitrum - request = new HttpPost("https://api.studio.thegraph.com/query/64403/arbitrum/version/latest"); + request = new HttpPost("https://gateway-arbitrum.network.thegraph.com/api/18ec3dcb6a75917897da2d5798fb98d3/subgraphs/id/BbFUyrr7KeB9VjxrSqWFDWAcsyDsGdbinrteLrPK5MVb"); break; case Constants.CHAIN_ID_ZKSYNC: // zksync - request = new HttpPost("https://api.studio.thegraph.com/query/64403/zksync/version/latest"); + request = new HttpPost("https://gateway-arbitrum.network.thegraph.com/api/18ec3dcb6a75917897da2d5798fb98d3/subgraphs/id/DzTmBT2V5kFQL6LpjC3iubYkusfj4HLVScCrAcT2DKGK"); break; case Constants.CHAIN_ID_POLYGON_ZKEVM: // polygon zkevm - request = new HttpPost("https://api.studio.thegraph.com/query/64403/polygonzkevm/version/latest"); + request = new HttpPost("https://gateway-arbitrum.network.thegraph.com/api/18ec3dcb6a75917897da2d5798fb98d3/subgraphs/id/A46TwCAxDy4upqLuS7bgXd14yLQdTjfS4AVPMNwWkZSR"); break; case Constants.CHAIN_ID_LINEA: //linea - request = new HttpPost("https://api.studio.thegraph.com/query/64403/linea/version/latest"); + request = new HttpPost("https://gateway-arbitrum.network.thegraph.com/api/18ec3dcb6a75917897da2d5798fb98d3/subgraphs/id/DatcM6CoN5u79XPx1wYFFnWXpHYcfDodkbycx2vSp25C"); break; } diff --git a/src/main/java/com/dl/officialsite/login/filter/LoginFilter.java b/src/main/java/com/dl/officialsite/login/filter/LoginFilter.java index e9f4b951..6de12100 100644 --- a/src/main/java/com/dl/officialsite/login/filter/LoginFilter.java +++ b/src/main/java/com/dl/officialsite/login/filter/LoginFilter.java @@ -61,6 +61,7 @@ public class LoginFilter extends OncePerRequestFilter { add("/defi/healthInfo"); add("/bounty/list"); add("/nft/WarCraft"); + add("/nft/raw/WarCraft"); }} ; private Set noAddrCheckApis = new HashSet() {{ diff --git a/src/main/java/com/dl/officialsite/nft/NFTController.java b/src/main/java/com/dl/officialsite/nft/NFTController.java index 4387c99f..f6683bb2 100644 --- a/src/main/java/com/dl/officialsite/nft/NFTController.java +++ b/src/main/java/com/dl/officialsite/nft/NFTController.java @@ -25,7 +25,7 @@ public class NFTController { * 获取 NFT 的元数据 */ @GetMapping("nft/{nftType}") - public BaseResponse verifyAndMint( + public BaseResponse fetchNftMetadata( @PathVariable String nftType, @NotNull @RequestParam("rank") Integer rank) { NFTMetadata nftMetadata = fileLoadConfig.get(nftType, rank); @@ -34,4 +34,19 @@ public BaseResponse verifyAndMint( } return BaseResponse.successWithData(nftMetadata); } + + /** + * 获取 NFT 的原始元数据 + */ + @GetMapping("nft/raw/{nftType}") + public Object fetchRawNftMetadata( + @PathVariable String nftType, + @NotNull @RequestParam("rank") Integer rank) { + NFTMetadata nftMetadata = fileLoadConfig.get(nftType, rank); + if (nftMetadata == null) { + return ""; + } + + return nftMetadata; + } } \ No newline at end of file diff --git a/src/main/java/com/dl/officialsite/nft/bean/MemberNFTMintRecord.java b/src/main/java/com/dl/officialsite/nft/bean/MemberNFTMintRecord.java index 0b78f561..135fc638 100644 --- a/src/main/java/com/dl/officialsite/nft/bean/MemberNFTMintRecord.java +++ b/src/main/java/com/dl/officialsite/nft/bean/MemberNFTMintRecord.java @@ -7,6 +7,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; +import org.hibernate.annotations.ColumnDefault; import org.hibernate.annotations.DynamicUpdate; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -57,6 +58,10 @@ public class MemberNFTMintRecord implements Serializable { @NotNull private String chainId; + @ColumnDefault("-1") + private int tokenId = -1; + + @ColumnDefault("-1") private int rankValue = -1; @CreatedDate diff --git a/src/main/java/com/dl/officialsite/nft/service/WarCraftContractService.java b/src/main/java/com/dl/officialsite/nft/service/WarCraftContractService.java index a50a1094..88108071 100644 --- a/src/main/java/com/dl/officialsite/nft/service/WarCraftContractService.java +++ b/src/main/java/com/dl/officialsite/nft/service/WarCraftContractService.java @@ -1,6 +1,6 @@ package com.dl.officialsite.nft.service; -import com.dl.officialsite.common.base.BaseResponse; +import com.dl.officialsite.common.exception.BizException; import com.dl.officialsite.nft.bean.MemberNFTMintRecord; import com.dl.officialsite.nft.bean.MemberNFTMintRecordRepository; import com.dl.officialsite.nft.config.ContractConfigService; @@ -8,6 +8,7 @@ import com.dl.officialsite.nft.contract.WarCraftContract; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.web3j.protocol.Web3j; @@ -32,21 +33,23 @@ public class WarCraftContractService { @Autowired private MemberNFTMintRecordRepository memberNFTMintRecordRepository; - public BaseResponse rank(String address, ContractNameEnum contractName, String chainId) { + public Pair rank(String address, ContractNameEnum contractName, String chainId) { String contractAddress = this.contractConfigService.getContractAddressByName(contractName, chainId); String rpcAddress = this.contractConfigService.getRpcAddressByName(contractName, chainId); if (StringUtils.isAnyBlank(contractAddress, rpcAddress)) { log.error("Fetch blank values of contractAddress:[{}] or rpcAddress:[{}] filtered by contractName:[{}] and chainId:[{}]", contractAddress, rpcAddress, contractName.getContractName(), chainId); - return BaseResponse.failWithReason("1204", "Fetch rank failed, please try again later."); + throw new BizException("1204", "Fetch rank failed, please try again later."); } Optional memberTaskRecordExists = memberNFTMintRecordRepository.findByAddressAndContractNameAndChainId(address, contractName.name(), chainId); - if(memberTaskRecordExists.isPresent() && memberTaskRecordExists.get().getRankValue() >= 0){ - return BaseResponse.successWithData(memberTaskRecordExists.get().getRankValue()); + if(memberTaskRecordExists.isPresent() + && memberTaskRecordExists.get().getRankValue() >= 0 + && memberTaskRecordExists.get().getTokenId() >= 0){ + return Pair.of(memberTaskRecordExists.get().getRankValue(), memberTaskRecordExists.get().getTokenId()); } Web3j web3j = Web3j.build(new HttpService(rpcAddress)); @@ -58,25 +61,26 @@ public BaseResponse rank(String address, ContractNameEnum contractName, String c BigInteger tokenId = contract.claimedTokenIdBy(address).sendAsync().get(TIMEOUT, TimeUnit.SECONDS); if (tokenId == null || tokenId.intValue() == 0) { log.error("No claim(tokenId) info found for address:[{}].", address); - return BaseResponse.failWithReason("200", "No claim info found."); + throw new BizException("200", "No claim info found."); } String rank = contract.tokenURIs(tokenId).sendAsync().get(TIMEOUT, TimeUnit.SECONDS); if (StringUtils.isBlank(rank)) { log.error("No rank info found for address:[{}] and tokenId:[{}].", address, tokenId.intValue()); - return BaseResponse.failWithReason("200", "No rank info found."); + throw new BizException("200", "No rank info found."); } - MemberNFTMintRecord memberNFTMintRecord = new MemberNFTMintRecord(); + MemberNFTMintRecord memberNFTMintRecord = memberTaskRecordExists.orElseGet(MemberNFTMintRecord::new); memberNFTMintRecord.setAddress(address); memberNFTMintRecord.setContractName(contractName); memberNFTMintRecord.setChainId(chainId); + memberNFTMintRecord.setTokenId(tokenId.intValue()); memberNFTMintRecord.setRankValue(Integer.parseInt(rank)); this.memberNFTMintRecordRepository.save(memberNFTMintRecord); - return BaseResponse.successWithData(rank); + return Pair.of(memberNFTMintRecord.getRankValue(), memberNFTMintRecord.getTokenId()); } catch (Exception e) { log.error("Call contract method:[claimedTokenIdBy] remote error.", e); - return BaseResponse.failWithReason("1205", "Fetch rank failed, please try again later."); + throw new BizException("1205", "Fetch rank failed, please try again later."); } } diff --git a/src/main/java/com/dl/officialsite/redpacket/RedPacketService.java b/src/main/java/com/dl/officialsite/redpacket/RedPacketService.java index 4f350ee7..e15a472e 100644 --- a/src/main/java/com/dl/officialsite/redpacket/RedPacketService.java +++ b/src/main/java/com/dl/officialsite/redpacket/RedPacketService.java @@ -6,9 +6,6 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; @@ -23,6 +20,10 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + /** * @ClassName TeamService * @Author jackchen @@ -42,16 +43,16 @@ public class RedPacketService { public CloseableHttpClient httpClient = HttpClients.createDefault(); - @Scheduled(cron = "${jobs.redpacket.corn:0/10 * * * * ?}") - @ConditionalOnProperty(name = "scheduler.enabled", havingValue = "true", matchIfMissing = true) - public void updateRedpacketStatus() { + @Scheduled(cron = "${jobs.redpacket.corn:0/10 * * * * ?}") + @ConditionalOnProperty(name = "scheduler.enabled", havingValue = "true", matchIfMissing = true) + public void updateRedpacketStatus() { log.info("schedule task begin --------------------- "); for (String chainId : chainConfig.getIds()) { try { updateRedpacketStatusByChainId(chainId); } catch (Exception e) { e.printStackTrace(); - log.error("updateRedpacketStatusByChainId: " + chainId + " error:"+ e.getMessage()); + log.error("updateRedpacketStatusByChainId: " + chainId + " error:" + e.getMessage()); } } } @@ -69,9 +70,9 @@ private void updateRedpacketStatusByChainId(String chainId) throws IOException { JsonObject data = jsonObject.getAsJsonObject("data"); JsonArray redpacketsArray = data.getAsJsonArray("redpackets"); JsonArray lastupdatesArray = data.getAsJsonArray("lastupdates"); - log.debug("lastupdatesArray"+ lastupdatesArray.toString()); + log.debug("lastupdatesArray" + lastupdatesArray.toString()); - // todo + // todo // if(lastupdatesArray.size() != 0){ // String lastTimestampFromGraph = lastupdatesArray.get(0).getAsJsonObject().get("lastupdateTimestamp").getAsString(); // @@ -117,11 +118,11 @@ private void updateRedpacketStatusByChainId(String chainId) throws IOException { // log.info("****** refunded"+ refunded); // log.info("****** allClaimed"+ allClaimed); - if(redPacket.getStatus() == null) { - log.info(redPacket.getName() + "****** upchain successfully" ); + if (redPacket.getStatus() == null) { + log.info(redPacket.getName() + "****** upchain successfully"); redPacket.setStatus(0); } - if( redPacket.getExpireTime()< System.currentTimeMillis()/1000){ + if (redPacket.getExpireTime() < System.currentTimeMillis() / 1000) { redPacket.setStatus(2); } if (allClaimed) { @@ -141,59 +142,66 @@ private void updateRedpacketStatusByChainId(String chainId) throws IOException { private HttpEntity getHttpEntityFromChain(String chainId) throws IOException { HttpPost request = null; - switch (chainId) { - case Constants.CHAIN_ID_OP: // op - request = new HttpPost("https://api.studio.thegraph.com/query/64274/optimism/version/latest"); - break; - case Constants.CHAIN_ID_SEPOLIA: //sepolia - request = new HttpPost("https://api.studio.thegraph.com/query/64274/sepolia/version/latest"); - break; - case Constants.CHAIN_ID_SCROLL: //scrool - request = new HttpPost("https://api.studio.thegraph.com/query/64274/scroll/version/latest"); - break; - case Constants.CHAIN_ID_ARBITRUM: //arbitrum - request = new HttpPost("https://api.studio.thegraph.com/query/64274/arbitrum/version/latest"); - break; - case Constants.CHAIN_ID_ZKSYNC: //zksync - request = new HttpPost("https://api.studio.thegraph.com/query/64274/zksync/version/latest"); - break; + switch (chainId) { + case Constants.CHAIN_ID_OP: // op + request = new HttpPost( + "https://gateway-arbitrum.network.thegraph.com/api/a5de3024bd9623fdc430f484c6c25ae1/subgraphs/id/G7LuMuUuWUW8UknEx8x2aVSeFtqpNMEKHvka2aKiDzRm"); + break; + case Constants.CHAIN_ID_SEPOLIA: //sepolia + request = new HttpPost( + "https://gateway-arbitrum.network.thegraph.com/api/a5de3024bd9623fdc430f484c6c25ae1/subgraphs/id/84hUXdB1qCmn8Du8bDmpLxxFSHjsgFCUKcrbtM4j5tp6"); + break; + case Constants.CHAIN_ID_SCROLL: //scrool + request = new HttpPost( + "https://gateway-arbitrum.network.thegraph.com/api/a5de3024bd9623fdc430f484c6c25ae1/subgraphs/id/6Ln5DVxZuYiY4VZzDQ2hzweBMRBpwW1SKRjeUy2YouRC"); + break; + case Constants.CHAIN_ID_ARBITRUM: //arbitrum + request = new HttpPost( + "https://gateway-arbitrum.network.thegraph.com/api/a5de3024bd9623fdc430f484c6c25ae1/subgraphs/id/9S1hiM5vzZ3m7o9SBpywHHcC8VZBSRUZTv3R8Npt56gS"); + break; + case Constants.CHAIN_ID_ZKSYNC: //zksync + request = new HttpPost( + "https://gateway-arbitrum.network.thegraph.com/api/a5de3024bd9623fdc430f484c6c25ae1/subgraphs/id/ERTqnTVeQKH8CVYwfGnqqZjtNDzgdnJRYQCgD4TY1gUX"); + break; case Constants.CHAIN_ID_POLYGON_ZKEVM: //polygon zkevm - request = new HttpPost("https://api.studio.thegraph.com/query/64274/polygonzkevm/version/latest"); - break; + request = new HttpPost( + "https://gateway-arbitrum.network.thegraph.com/api/a5de3024bd9623fdc430f484c6c25ae1/subgraphs/id/5DsufFHE6P7tK7QT1mGCPrQEKURD2E1SSHAyCSzf5CAg"); + break; case Constants.CHAIN_ID_LINEA: //linea - request = new HttpPost("https://api.studio.thegraph.com/query/64274/linea/version/latest"); - break; + request = new HttpPost( + "https://gateway-arbitrum.network.thegraph.com/api/a5de3024bd9623fdc430f484c6c25ae1/subgraphs/id/958YHrTJturbhR6uwRyPu1wmBNiXivNkLMPY7tUiL4wD"); + break; - } + } request.setHeader("Content-Type", "application/json"); // Define your GraphQL query long currentTimeMillis = System.currentTimeMillis(); - long time = currentTimeMillis / 1000 - 3600*24*90; - // time = Math.max(time, 1703751860); + long time = currentTimeMillis / 1000 - 3600 * 24 * 90; + // time = Math.max(time, 1703751860); String creationTimeGtValue = String.valueOf(time); String graphQL = "\" {" + - " redpackets (where: { creationTime_gt: "+ creationTimeGtValue + " }) {" + - " id " + - " refunded " + - " lock " + - " name " + - " creationTime " + - " allClaimed " + - " claimers {" + - " claimer" + - " claimedValue " + - " }" + - " }" + - " lastupdates (orderBy : lastupdateTimestamp , orderDirection: desc) { lastupdateTimestamp } " + - - "}\""; + " redpackets (where: { creationTime_gt: " + creationTimeGtValue + " }) {" + + " id " + + " refunded " + + " lock " + + " name " + + " creationTime " + + " allClaimed " + + " claimers {" + + " claimer" + + " claimedValue " + + " }" + + " }" + + " lastupdates (orderBy : lastupdateTimestamp , orderDirection: desc) { lastupdateTimestamp } " + + + "}\""; String query = "{ \"query\": " + - graphQL + - " }"; + graphQL + + " }"; request.setEntity(new StringEntity(query)); HttpResponse response = httpClient.execute(request); diff --git a/src/main/java/com/dl/officialsite/sharing/SharingService.java b/src/main/java/com/dl/officialsite/sharing/SharingService.java index 4e149b2a..b619540e 100644 --- a/src/main/java/com/dl/officialsite/sharing/SharingService.java +++ b/src/main/java/com/dl/officialsite/sharing/SharingService.java @@ -117,12 +117,12 @@ public void updateSharing(UpdateSharingReq req, String address) { sharing.setYoutubeLink(req.getYoutubeLink()); this.sharingRepository.save(sharing); - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); +/* SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); String formatDate = format.format(req.getDate()); applicationContext.publishEvent(new EventNotify(Member.class, BotEnum.TELEGRAM, ChannelEnum.SHARING, NotifyMessageFactory.sharingMessage("‼️‼️Edit Share Info‼️‼️", member.getNickName(), req.getTheme(), - formatDate))); + formatDate)));*/ } else { throw new BizException(CodeEnums.SHARING_NOT_OWNER_OR_ADMIN); }