diff --git a/src/main/java/com/dl/officialsite/nft/bean/MemberNFTMintRecord.java b/src/main/java/com/dl/officialsite/nft/bean/MemberNFTMintRecord.java new file mode 100644 index 00000000..0b78f561 --- /dev/null +++ b/src/main/java/com/dl/officialsite/nft/bean/MemberNFTMintRecord.java @@ -0,0 +1,65 @@ +package com.dl.officialsite.nft.bean; + +import com.dl.officialsite.nft.constant.ContractNameEnum; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import org.hibernate.annotations.DynamicUpdate; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EntityListeners; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.UniqueConstraint; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@ToString +@EqualsAndHashCode(onlyExplicitlyIncluded = true) +@EntityListeners(AuditingEntityListener.class) +@Entity +@DynamicUpdate +@Table(name = "member_nft_mint_record", schema = "dl", uniqueConstraints = { + @UniqueConstraint(name = "unique_mint_record", columnNames = { + "address", "contractName", "chainId" + }) +}) +public class MemberNFTMintRecord implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(length = 42) + @NotNull + private String address; + + @NotNull + @Column(length = 16) + @Enumerated(EnumType.STRING) + private ContractNameEnum contractName; + + @Column(length = 32) + @NotNull + private String chainId; + + private int rankValue = -1; + + @CreatedDate + @Column(updatable = false) + private Long mintTime; +} diff --git a/src/main/java/com/dl/officialsite/nft/bean/MemberNFTMintRecordRepository.java b/src/main/java/com/dl/officialsite/nft/bean/MemberNFTMintRecordRepository.java new file mode 100644 index 00000000..ad03fbf1 --- /dev/null +++ b/src/main/java/com/dl/officialsite/nft/bean/MemberNFTMintRecordRepository.java @@ -0,0 +1,18 @@ +package com.dl.officialsite.nft.bean; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.Optional; + +public interface MemberNFTMintRecordRepository + extends JpaRepository, JpaSpecificationExecutor { + + @Query(value = "select * from member_nft_mint_record where address =:address and contract_name=:contractName and " + + "chain_id=:chainId", nativeQuery = true) + Optional findByAddressAndContractNameAndChainId(@Param("address") String address, + @Param("contractName") String contractName, + @Param("chainId") String chainId); +} 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 6da9c193..fa8d5354 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,8 @@ package com.dl.officialsite.nft.service; import com.dl.officialsite.common.base.BaseResponse; +import com.dl.officialsite.nft.bean.MemberNFTMintRecord; +import com.dl.officialsite.nft.bean.MemberNFTMintRecordRepository; import com.dl.officialsite.nft.config.ContractConfigService; import com.dl.officialsite.nft.constant.ContractNameEnum; import com.dl.officialsite.nft.contract.WarCraftContract; @@ -16,6 +18,7 @@ import org.web3j.tx.gas.StaticGasProvider; import java.math.BigInteger; +import java.util.Optional; import java.util.concurrent.TimeUnit; @Slf4j @@ -27,6 +30,8 @@ public class WarCraftContractService { @Autowired private ContractConfigService contractConfigService; + @Autowired + private MemberNFTMintRecordRepository memberNFTMintRecordRepository; public BaseResponse rank(String address, ContractNameEnum contractName, String chainId) { String contractAddress = this.contractConfigService.getContractAddressByName(contractName, chainId); @@ -38,6 +43,13 @@ public BaseResponse rank(String address, ContractNameEnum contractName, String c return BaseResponse.failWithReason("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()); + } + Web3j web3j = Web3j.build(new HttpService(rpcAddress)); ClientTransactionManager transactionManager = new ClientTransactionManager(web3j, ZERO_ADDRESS); @@ -45,21 +57,28 @@ public BaseResponse rank(String address, ContractNameEnum contractName, String c try { BigInteger tokenId = contract.claimedTokenIdBy(address).sendAsync().get(TIMEOUT, TimeUnit.SECONDS); - if (tokenId == null || tokenId.intValue() == 0){ + if (tokenId == null || tokenId.intValue() == 0) { log.error("No claim(tokenId) info found for address:[{}].", address); return BaseResponse.failWithReason("1206", "No claim info found."); } String rank = contract.tokenURI(tokenId).sendAsync().get(TIMEOUT, TimeUnit.SECONDS); - if (StringUtils.isBlank(rank)){ + if (StringUtils.isBlank(rank)) { log.error("No rank info found for address:[{}] and tokenId:[{}].", address, tokenId.intValue()); return BaseResponse.failWithReason("1206", "No rank info found."); } int rankValue = RankExtractorUtil.extractParameterValueFromUrl(rank, "rank"); - if (rankValue < 0){ + if (rankValue < 0) { log.error("Invalid rank value:[{}] found in url:[{}].", rankValue, rank); return BaseResponse.failWithReason("1206", "No rank info found."); } + + MemberNFTMintRecord memberNFTMintRecord = new MemberNFTMintRecord(); + memberNFTMintRecord.setAddress(address); + memberNFTMintRecord.setContractName(contractName); + memberNFTMintRecord.setChainId(chainId); + memberNFTMintRecord.setRankValue(rankValue); + this.memberNFTMintRecordRepository.save(memberNFTMintRecord); return BaseResponse.successWithData(rankValue); } catch (Exception e) { log.error("Call contract method:[claimedTokenIdBy] remote error.", e);