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

以太坊合约









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


阅读更多

更多精彩内容