package com.fingerchar.service;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.web3j.abi.datatypes.generated.Uint256;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fingerchar.base.entity.BaseEntity;
import com.fingerchar.base.service.IBaseService;
import com.fingerchar.constant.CommonStatus;
import com.fingerchar.constant.NoticeType;
import com.fingerchar.constant.SysConfConstant;
import com.fingerchar.dao.ext.FcOrderLogExtMapper;
import com.fingerchar.domain.FcContractNft;
import com.fingerchar.domain.FcNftItems;
import com.fingerchar.domain.FcOrder;
import com.fingerchar.domain.FcOrderLog;
import com.fingerchar.domain.FcPayToken;
import com.fingerchar.domain.FcSystem;
import com.fingerchar.domain.FcTxOrder;
import com.fingerchar.utils.NftDappEventUtils;
import com.fingerchar.vo.EventValuesExt;
@Service
public class NftEventService {
private static final Logger logger = LoggerFactory.getLogger(NftEventService.class);
public static final String ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
@Autowired
private IBaseService baseService;
@Autowired
FcOrderLogExtMapper orderLogExtMapper;
@Autowired
FcNoticeService noticeService;
@Autowired
FcSystemConfigService configService;
@Transactional(rollbackFor = Exception.class)
public void processEvent(Map<String, List<EventValuesExt>> map, String block) throws Exception {
if (map.isEmpty()) {
this.saveLastBlock(block);
return;
}
List<FcOrderLog> list = new ArrayList<>();
List<EventValuesExt> valueList = sortLog(map.get(NftDappEventUtils.BUY_EVENT.getName()));
Map<String, Integer> orderTypeMap = new HashMap<>();
if(null != valueList && !valueList.isEmpty()) {
this.processBuyEvent(valueList, list, orderTypeMap);
}
String exchangeToken = this.configService.get(SysConfConstant.NFT_EXCHANGE);
if (StringUtils.isEmpty(exchangeToken)) {
throw new Exception("Unkown nft exchange token");
}
valueList = sortLog(map.get(NftDappEventUtils.CANCEL_EVENT.getName()));
if(null != valueList && !valueList.isEmpty()) {
this.processCancelEvent(valueList, list);
}
valueList = sortLog(map.get(NftDappEventUtils.TRANSFER_EVENT.getName()));
if(null != valueList && !valueList.isEmpty()) {
Map<String, List<EventValuesExt>> valueMap = new HashMap<>();
valueList.stream().forEach(vo -> {
if (null == valueMap.get(vo.getTxHash())) {
valueMap.put(vo.getTxHash(), new ArrayList<>());
}
valueMap.get(vo.getTxHash()).add(vo);
});
this.processTransferEvent(valueMap, list, orderTypeMap);
}
valueList = sortLog(map.get(NftDappEventUtils.SECONDARYSALEFEES_EVENT.getName()));
if(null != valueList && !valueList.isEmpty()) {
this.processRoyaltiesEvent(valueList);
}
this.addOrderLog(list);
this.saveLastBlock(block);
}
private List<EventValuesExt> sortLog(List<EventValuesExt> list) {
if (null == list) {
return null;
}
Collections.sort(list, new Comparator<EventValuesExt>() {
public int compare(EventValuesExt val1, EventValuesExt val2) {
return val1.getBlockNumber().compareTo(val2.getBlockNumber());
}
});
return list;
}
@Transactional(rollbackFor = Exception.class)
private void processRoyaltiesEvent(List<EventValuesExt> valueList) {
if (valueList.isEmpty()) {
return;
}
int len = valueList.size();
for (int i = 0; i < len; i++) {
this.processRoyaltiesEvent(valueList.get(i));
}
}
@Transactional(rollbackFor = Exception.class)
private void processRoyaltiesEvent(EventValuesExt eventValues) {
BigInteger tokenId = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue();
@SuppressWarnings("unchecked")
List<Uint256> bps = (List<Uint256>) eventValues.getNonIndexedValues().get(2).getValue();
QueryWrapper<FcContractNft> wrapper = new QueryWrapper<>();
wrapper.eq(FcContractNft.ADDRESS, eventValues.getAddress())
.eq(FcContractNft.TOKEN_ID, tokenId.toString());
List<FcContractNft> nftList = this.baseService.findByCondition(FcContractNft.class, wrapper);
if (null == nftList || nftList.isEmpty()) {
return;
}
Set<Long> idSet = nftList.stream().map(FcContractNft::getId).collect(Collectors.toSet());
UpdateWrapper<FcContractNft> uwrapper = new UpdateWrapper<>();
List<Long> bpsTemp = bps.stream().map(bi -> bi.getValue().longValueExact()).collect(Collectors.toList());
uwrapper.set(FcContractNft.ROYALTIES, JSON.toJSONString(bpsTemp));
uwrapper.in(BaseEntity.ID, idSet);
this.baseService.updateByCondition(FcContractNft.class, uwrapper);
}
@Transactional(rollbackFor = Exception.class)
private void addOrderLog(List<FcOrderLog> logList) {
if (logList.size() > 0) {
this.baseService.saveBatch(logList);
Set<String> txHashList = logList.stream().map(FcOrderLog::getTxHash).collect(Collectors.toSet());
if (txHashList.size() > 0) {
UpdateWrapper<FcTxOrder> wrapper = new UpdateWrapper<>();
wrapper.set(FcTxOrder.IS_SYNC, true);
wrapper.in(FcTxOrder.TX_HASH, txHashList);
this.baseService.updateByCondition(FcTxOrder.class, wrapper);
}
}
}
@Transactional(rollbackFor = Exception.class)
private void processBuyEvent(List<EventValuesExt> buyList, List<FcOrderLog> logList, Map<String, Integer> orderTypeMap) throws Exception {
if (buyList.isEmpty()) {
return;
}
int len = buyList.size();
for (int i = 0; i < len; i++) {
this.processBuyEvent(buyList.get(i), logList, orderTypeMap);
}
}
@Transactional(rollbackFor = Exception.class)
private void processBuyEvent(EventValuesExt eventValue, List<FcOrderLog> logList, Map<String, Integer> orderTypeMap) throws Exception {
String txHash = eventValue.getTxHash();
FcTxOrder txOrder = this.getByHash(txHash);
if (null != txOrder) {
logger.warn("tx_hash为" + txHash + "已经处理!");
return;
}
String sellToken = (String) eventValue.getIndexedValues().get(0).getValue();
BigInteger sellTokenId = (BigInteger) eventValue.getIndexedValues().get(1).getValue();
BigInteger sellValue = (BigInteger) eventValue.getNonIndexedValues().get(0).getValue();
String owner = (String) eventValue.getNonIndexedValues().get(1).getValue();
String buyToken = (String) eventValue.getNonIndexedValues().get(2).getValue();
BigInteger buyTokenId = (BigInteger) eventValue.getNonIndexedValues().get(3).getValue();
BigInteger buyValue = (BigInteger) eventValue.getNonIndexedValues().get(4).getValue();
String buyer = (String) eventValue.getNonIndexedValues().get(5).getValue();
BigInteger sal
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
去中心化NFT市场, 借鉴了Rarible,实现免手续费离线签名,帮助用户在交易NFT的同时,减少手续费消耗。可部署在流行的公链上。采用流行的Java与Vue语言开发,结合当下流行的后端技术Spring Boot后端框架和主流的前端框架Vue3,移动端采用uniapp技术 - 后端: Spring Boot Java框架 - PC前端: Vue前端框架 - 移动端: Uniapp前端框架
资源推荐
资源详情
资源评论
收起资源包目录
springboot + vue前后端分离的NFT数藏盲盒系统 (952个子文件)
.classpath 2KB
.classpath 1KB
.classpath 1KB
.classpath 1023B
mvnw.cmd 6KB
index.css 1.28MB
date-picker.css 83KB
cascader.css 81KB
iconfont.css 78KB
pagination.css 73KB
select.css 63KB
transfer.css 60KB
time-picker.css 57KB
table.css 51KB
message-box.css 50KB
time-select.css 42KB
slider.css 42KB
cascader-panel.css 41KB
col.css 38KB
dropdown.css 36KB
table-column.css 34KB
autocomplete.css 33KB
tree.css 30KB
calendar.css 27KB
upload.css 26KB
base.css 24KB
tabs.css 24KB
iconfont.css 24KB
input-number.css 23KB
button.css 21KB
menu.css 19KB
icon.css 17KB
checkbox.css 16KB
color-picker.css 14KB
input.css 13KB
dialog.css 13KB
collapse.css 13KB
select-dropdown.css 13KB
popover.css 12KB
step.css 12KB
drawer.css 11KB
radio.css 11KB
tag.css 11KB
radio-button.css 10KB
image.css 9KB
demo.css 8KB
demo.css 8KB
form.css 8KB
carousel.css 8KB
tooltip.css 8KB
progress.css 8KB
link.css 8KB
alert.css 7KB
message.css 7KB
switch.css 7KB
loading.css 7KB
notification.css 7KB
popper.css 7KB
timeline-item.css 7KB
scrollbar.css 6KB
breadcrumb.css 6KB
carousel-item.css 6KB
display.css 6KB
row.css 6KB
badge.css 6KB
normalize.css 6KB
divider.css 6KB
page-header.css 6KB
rate.css 6KB
avatar.css 6KB
card.css 5KB
option-group.css 5KB
option.css 5KB
backtop.css 5KB
popconfirm.css 5KB
main.css 5KB
timeline.css 5KB
header.css 5KB
footer.css 5KB
radio-group.css 5KB
spinner.css 4KB
reset.css 3KB
container.css 3KB
steps.css 3KB
aside.css 3KB
element-variables.css 2KB
base.css 1KB
iconfont.css 474B
font.css 159B
checkbox-button.css 0B
button-group.css 0B
breadcrumb-item.css 0B
form-item.css 0B
infinite-scroll.css 0B
menu-item.css 0B
menu-item-group.css 0B
checkbox-group.css 0B
dropdown-item.css 0B
tab-pane.css 0B
dropdown-menu.css 0B
共 952 条
- 1
- 2
- 3
- 4
- 5
- 6
- 10
资源评论
- weixin_390424582022-07-05感谢资源主的分享,很值得参考学习,资源价值较高,支持!
- 学无止境qwer2022-09-03非常有用的资源,可以直接使用,对我很有用,果断支持!
- lanjch2022-08-05资源很好用,有较大的参考价值,资源不错,支持一下。
办公模板库素材蛙
- 粉丝: 1658
- 资源: 2299
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功