【以太坊】以太币与合约代币的区块扫描

以太坊合约









 //根据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();
		}
	}


猜你喜欢

转载自blog.csdn.net/harwey_it/article/details/80312077