比特币充值到账提醒程序

2021-04-18 16:06
395
0
@Data
public abstract class Watcher implements Runnable{
    private Logger logger = LoggerFactory.getLogger(Watcher.class);
    private boolean stop = false;
    //默认同步间隔20秒
    private Long checkInterval = 2000L;
    private Long currentBlockHeight = 0L;
    private int step = 5;
    //区块确认数
    private int confirmation = 3;
    private DepositEvent depositEvent;
    private Coin coin;
    private WatcherLogService watcherLogService;

    public void check(){
        try {
            Long networkBlockNumber = getNetworkBlockHeight() - confirmation + 1;
            if (currentBlockHeight < networkBlockNumber) {
                long startBlockNumber = currentBlockHeight + 1;
                currentBlockHeight = (networkBlockNumber - currentBlockHeight > step) ? currentBlockHeight + step : networkBlockNumber;
                logger.info("replay block from {} to {}", startBlockNumber, currentBlockHeight);
                List<Deposit> deposits = replayBlock(startBlockNumber, currentBlockHeight);
                if(deposits != null) {
                 deposits.forEach(deposit -> {
                       depositEvent.onConfirmed(deposit);
                   });
                   //记录日志
                 watcherLogService.update(coin.getName(), currentBlockHeight);
              }else {
                 logger.info("扫块失败!!!");
                 // 未扫描成功
                 currentBlockHeight = startBlockNumber - 1;
              }
            } else {
                logger.info("Already latest height: {}, networkBlockHeight: {},nothing to do!", currentBlockHeight, networkBlockNumber);
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }

    public abstract List<Deposit> replayBlock(Long startBlockNumber, Long endBlockNumber);

    public abstract Long getNetworkBlockHeight();

    @Override
    public void run() {
        stop = false;
        long nextCheck = 0;
        while(!(Thread.interrupted() || stop)) {
            if (nextCheck <= System.currentTimeMillis()) {
                try {
                    nextCheck = System.currentTimeMillis() + checkInterval;
                    logger.info("check...");
                    check();
                } catch (Exception ex) {
                    logger.info(ex.getMessage());
                }
            }
            else {
                try {
                    Thread.sleep(Math.max(nextCheck - System.currentTimeMillis(), 100));
                } catch (InterruptedException ex) {
                    logger.info(ex.getMessage());
                }
            }
        }
    }
}

 

 

//////////////////////////////////////////////////////////

@Component
public class BitcoinWatcher extends Watcher{
    @Autowired
    private BitcoinRPCClient rpcClient;
    @Autowired
    private AccountService accountService;
    private Logger logger = LoggerFactory.getLogger(Watcher.class);
    @Override
    public List<Deposit> replayBlock(Long startBlockNumber, Long endBlockNumber) {
        List<Deposit> deposits = new ArrayList<Deposit>();
        try {
            for (Long blockHeight = startBlockNumber; blockHeight <= endBlockNumber; blockHeight++) {
                String blockHash = rpcClient.getBlockHash(blockHeight.intValue());
                //获取区块
                Bitcoin.Block block =  rpcClient.getBlock(blockHash);
                List<String> txids = block.tx();
                logger.info("获取区块(" + blockHeight + ")交易列表,总交易数:" + txids.size() + "");
                //遍历区块中的交易
                for(String txid:txids){
                    Bitcoin.RawTransaction transaction =  rpcClient.getRawTransaction(txid);
                    List<Bitcoin.RawTransaction.Out> outs = transaction.vOut();
                    if(outs != null) {
                        for (Bitcoin.RawTransaction.Out out : outs) {
                            if (out.scriptPubKey() != null) {
                               List<String> addresses = out.scriptPubKey().addresses();
                               if(addresses != null && addresses.size() > 0) {
                                   String address = out.scriptPubKey().addresses().get(0);
                                   BigDecimal amount = new BigDecimal(out.value());
                                   if (accountService.isAddressExist(address)) {
                                      logger.info("发现充值地址(" + address + "),充值金额:" + amount + " BTC");
                                       Deposit deposit = new Deposit();
                                       deposit.setTxid(transaction.txId());
                                       deposit.setBlockHeight((long) block.height());
                                       deposit.setBlockHash(transaction.blockHash());
                                       deposit.setAmount(amount);
                                       deposit.setAddress(address);
                                       deposit.setTime(transaction.time());
                                       deposits.add(deposit);
                                   }
                               }
                            }
                        }
                    }
                }
            }
        }
        catch (Exception e){
            e.printStackTrace();
            return null;
        }
        return deposits;
    }



    @Override
    public Long getNetworkBlockHeight() {
        try {
            return Long.valueOf(rpcClient.getBlockCount());
        }
        catch (Exception e){
            e.printStackTrace();
            return 0L;
        }
    }
}

全部评论