以太坊合约
//根据txId查询交易记录是否存在 存在:提现 不存在:充值
/* 提现逻辑
* 1、判断区块交易中为状态
* 2、成功 更新交易状态
* 3、不成功 (1)更新交易状态 (2)返还账号金额
*/
/* 充值逻辑
* 1、更具coinid和to查询 判断 是系统用户充值的 && 交易状态成功
* 2、添加充值记录
* 3、给用户金额充值 返回金额 更新钱包
* 4、首次充值奖励
*/
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void listBlock(Web3j web3j)
throws IOException, Exception, BCException {
Long tokenBlockHeight = jobUtils.getETHBlockHeight();
Long latestBlockNumber = web3j.ethBlockNumber().send().getBlockNumber().longValue();
logger.info("最新区块高度:{},扫描区块高度:{}",latestBlockNumber, tokenBlockHeight);
if(latestBlockNumber<tokenBlockHeight) {
tokenBlockHeight = latestBlockNumber;
try {
logger.warn("扫描区块高度大于当前最新区块高度");
Thread.sleep(10000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
logger.info("当前扫描区块高度:{}", tokenBlockHeight);
EthBlock block = null;
if(tokenBlockHeight>0) {
block = web3j.ethGetBlockByNumber(DefaultBlockParameter.valueOf(BigInteger.valueOf(tokenBlockHeight)), true).send();
}
if(block!=null){
List<TransactionResult> list=block.getBlock().getTransactions();
for(TransactionResult result : list){
TransactionObject object=(TransactionObject) result;
if(object==null) {
logger.warn("当前扫描区块object为空 休眠3秒");
Thread.sleep(3000);
return;
}
List<FVirtualCapitalOperationDTO> fvirtualcaptualoperations = this.fVirtualCapitalOperationMapper.selectByTxid(object.getHash());
if (fvirtualcaptualoperations.size() > 0) { //交易记录列表中有该笔交易,说明是提现
//logger.info(object.getHash() +" 是否存在该笔交易: " + (fvirtualcaptualoperations.size() > 0));
FVirtualCapitalOperationDTO opDto = fvirtualcaptualoperations.get(0);
//logger.info("交易类型是否为提现:" +(opDto.getFtype()==VirtualCapitalOperationTypeEnum.COIN_OUT.getCode()?"提现":"充值"));
if(opDto.getFtype()==VirtualCapitalOperationTypeEnum.COIN_OUT.getCode()) { //交易类型为 提现
//查询该笔交易状态
boolean txStatus = false;
EthGetTransactionReceipt receipt = web3j.ethGetTransactionReceipt(object.getHash()).send();
if(receipt.getTransactionReceipt().isPresent()){
TransactionReceipt re=receipt.getTransactionReceipt().get();
txStatus = HexToBoolean(re.getStatus());
}
//txStatus = true;
//logger.info("区块交易中为状态成功:" +txStatus);
//区块交易中为状态成功
if(txStatus) {
//更新交易状态
opDto.setFstatus(VirtualCapitalOperationOutStatusEnum.OperationSuccess);
opDto.setFupdatetime(Utils.getTimestamp());
opDto.setFconfirmations(1);
opDto.setFblocknumber(block.getBlock().getNumber().intValue());
if (this.fVirtualCapitalOperationMapper.updateByPrimaryKey(opDto) <= 0) {
logger.warn("提现交易更新为(成功状态)异常 hash:{}", object.getHash());
throw new Exception();
}
//logger.info("完成更新交易状态为成功");
} else { //区块交易中为状态失败
//1、更新交易状态
opDto.setFstatus(VirtualCapitalOperationOutStatusEnum.OperationFailed);
opDto.setFupdatetime(Utils.getTimestamp());
opDto.setFconfirmations(1);
opDto.setFblocknumber(block.getBlock().getNumber().intValue());
if (this.fVirtualCapitalOperationMapper.updateByPrimaryKey(opDto) <= 0) {
logger.warn("提现交易更新为(失败状态)异常 hash:{}", object.getHash());
throw new Exception();
}
//2、返还金额 更新钱包
/*UserCoinWallet userCoinWallet = userCoinWalletMapper.selectLock(opDto.getFuid(), opDto.getFcoinid());
if (userCoinWallet == null) {
continue;
}
userCoinWallet.setTotal(MathUtils.add(userCoinWallet.getTotal(), opDto.getFamount()));
if(this.userCoinWalletMapper.update(userCoinWallet)<=0) {
throw new Exception();
}
logger.info("完成返还金额");*/
}
} else {
continue;
}
} else {//交易记录列表中有该笔交易,说明是充值
//=================================
List<SystemCoinType> coinTypes = jobUtils.getCoinTypeList();
if (coinTypes != null && coinTypes.size()>0) {
for (SystemCoinType coinType : coinTypes) {
if (coinType.getCoinType().equals(SystemCoinSortEnum.ETH.getCode()) || coinType.getCoinType().equals(SystemCoinSortEnum.ETC.getCode())) {
//----------------------------
if(object.getTo()==null) { //如果to为空的话,说明该条交易是建合约交易
continue;
}
BigDecimal tranAmount = new BigDecimal(this.ETHBalanceHexToStr(object.getValue(), 18));
String to = object.getTo().trim();
String input = object.get().getInput();
//判断如果是代币,那么金额在input数据中
if(tranAmount.compareTo(BigDecimal.ZERO)==0) {
//是合约代币交易, 判断当前合约代币名称是否与当前币种名称一致, 不一致则continue
if(!coinType.getContractAccount().equals(object.getTo().trim())) {
continue;
}
if(input!=null && input.length()>136){
String tranMethodId=input.substring(0,10);
if("0xa9059cbb".equals(tranMethodId)){ // transfer param: to - balance 事件ID,固定的,该事件为转账ID
List<Type> values=FunctionReturnDecoder.decode(input.substring(input.length()-64,input.length()), org.web3j.abi.Utils.convert(Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {})));
if(!values.isEmpty()){
String value=values.get(0).getValue().toString();
tranAmount = new BigDecimal(ETHBalanceToStr(value, coinType.getContractWei()));
}
String toAddress=input.substring(10,74);
List<Type> addressType = FunctionReturnDecoder.decode(toAddress, org.web3j.abi.Utils.convert(Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {})));
if(!addressType.isEmpty()){
to = addressType.get(0).getValue().toString();
}
}else if("0x23b872dd".equals(tranMethodId)) { //transferFrom param:from - to - balance
List<Type> values=FunctionReturnDecoder.decode(input.substring(input.length()-64,input.length()), org.web3j.abi.Utils.convert(Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {})));
if(!values.isEmpty()){
String value=values.get(0).getValue().toString();
tranAmount = new BigDecimal(ETHBalanceToStr(value, coinType.getContractWei()));
}
String toAddress=input.substring(74,138);
List<Type> addressType = FunctionReturnDecoder.decode(toAddress, org.web3j.abi.Utils.convert(Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {})));
if(!addressType.isEmpty()){
to = addressType.get(0).getValue().toString();
}
} else {
logger.info("非转账交易 hash:{}", object.getHash());
break;
}
}
}
//交易记录列表中有该笔交易,说明是充值
int coinid = coinType.getId();
FUserVirtualAddressDTO vaDto = fUserVirtualAddressMapper.selectByCoinAndAddress(16, to);
if(vaDto!=null) { //判断 是系统用户充值的 && 交易状态成功
//logger.info(coinid +" : " + object.getTo() + "用户地址中是存在:" +(vaDto!=null));
//查询该笔交易状态
boolean txStatus = false;
EthGetTransactionReceipt receipt = web3j.ethGetTransactionReceipt(object.getHash()).send();
if(receipt.getTransactionReceipt().isPresent()){
TransactionReceipt re=receipt.getTransactionReceipt().get();
txStatus = HexToBoolean(re.getStatus());
}
//logger.info("区块交易中为状态成功:" +txStatus);
//txStatus = true;
if(txStatus) {
//1、添加充值记录
FVirtualCapitalOperationDTO fvirtualcaptualoperation = new FVirtualCapitalOperationDTO();
fvirtualcaptualoperation.setFuid(vaDto.getFuid());
fvirtualcaptualoperation.setFamount(tranAmount);
fvirtualcaptualoperation.setFfees(BigDecimal.ZERO);
fvirtualcaptualoperation.setFcoinid(coinid);
fvirtualcaptualoperation.setFtype(VirtualCapitalOperationTypeEnum.COIN_IN.getCode());
fvirtualcaptualoperation.setFstatus(VirtualCapitalOperationInStatusEnum.SUCCESS);
fvirtualcaptualoperation.setFhasowner(true);
fvirtualcaptualoperation.setFbtcfees(BigDecimal.ZERO);
fvirtualcaptualoperation.setFblocknumber(block.getBlock().getNumber().intValue());
fvirtualcaptualoperation.setFconfirmations(1);
fvirtualcaptualoperation.setFrechargeaddress(to);
fvirtualcaptualoperation.setFcreatetime(Utils.getTimestamp());
fvirtualcaptualoperation.setFupdatetime(Utils.getTimestamp());
fvirtualcaptualoperation.setVersion(0);
fvirtualcaptualoperation.setFsource(DataSourceEnum.WEB.getCode());
fvirtualcaptualoperation.setFuniquenumber(object.getHash());
if(this.fVirtualCapitalOperationMapper.insert(fvirtualcaptualoperation)<=0) {
logger.warn("充值交易插入异常 hash:{}", object.getHash());
throw new Exception();
}
//2、给用户金额充值 返回金额 更新钱包
UserCoinWallet userCoinWallet = userCoinWalletMapper.selectLock(fvirtualcaptualoperation.getFuid(), fvirtualcaptualoperation.getFcoinid());
if (userCoinWallet == null) {
logger.warn("获取用户钱包对象失败,hash:{}, uid:{}, coinid:{}", object.getHash(), fvirtualcaptualoperation.getFuid(), fvirtualcaptualoperation.getFcoinid());
continue;
}
userCoinWallet.setTotal(MathUtils.add(userCoinWallet.getTotal(), fvirtualcaptualoperation.getFamount()));
if(this.userCoinWalletMapper.update(userCoinWallet)<=0) {
logger.warn("更新资产数据失败,hash:{}, uid:{}, coinid:{}, amount:{}", object.getHash(), fvirtualcaptualoperation.getFuid(), fvirtualcaptualoperation.getFcoinid(), fvirtualcaptualoperation.getFamount());
throw new Exception();
}
BigDecimal last = jobUtils.getLastPrice(fvirtualcaptualoperation.getFcoinid());
BigDecimal amount = MathUtils.mul(fvirtualcaptualoperation.getFamount(), last);
scoreHelper.SendUserScore(fvirtualcaptualoperation.getFuid(), amount, ScoreTypeEnum.RECHARGE.getCode()
, "充值" + coinType.getShortName() + ":" + fvirtualcaptualoperation.getFamount());
//首次充值奖励
boolean isFirstRecharge = isFirstCharge(fvirtualcaptualoperation.getFuid());
if(isFirstRecharge) {
scoreHelper.SendUserScore(fvirtualcaptualoperation.getFuid(), BigDecimal.ZERO, ScoreTypeEnum.FIRSTCHARGE.getCode(), ScoreTypeEnum.FIRSTCHARGE.getValue().toString());
}
mqSend.SendUserAction(fvirtualcaptualoperation.getFagentid(), fvirtualcaptualoperation.getFuid(),
LogUserActionEnum.COIN_RECHARGE, fvirtualcaptualoperation.getFcoinid(), 0,
fvirtualcaptualoperation.getFamount());
// 风控短信
if (fvirtualcaptualoperation.getFamount().compareTo(coinType.getRiskNum()) >= 0) {
String riskphone = jobUtils.getSystemArgs(ArgsConstant.RISKPHONE);
String[] riskphones = riskphone.split("#");
if (riskphones.length > 0) {
FUser fuser = userMapper.selectByPrimaryKey(fvirtualcaptualoperation.getFuid());
for (String string : riskphones) {
try {
validateHelper.smsRiskManage(fuser.getFloginname(), string, PlatformEnum.BC.getCode(),
BusinessTypeEnum.SMS_RISKMANAGE.getCode(), "充值",
fvirtualcaptualoperation.getFamount(), coinType.getName());
} catch (Exception e) {
logger.error("updateCoinCome riskphones err");
e.printStackTrace();
}
}
}
}
logger.info("完成添加充值记录 hash:{}", object.getHash());
}
break;
}
//----------------------------
}
}
}
//=================================
}
}
tokenBlockHeight = tokenBlockHeight + 1;
} else {
logger.info("block is null");
}
//System.out.println("===============tokenBlockHeight: " + tokenBlockHeight);
jobUtils.setETHBlockHeight(tokenBlockHeight);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}