比特币转账功能开发

比特币转账

和其他数字货币一样,比特币提供了我们底层的转账接口,当我们已经搭建完本地的节点服务,也已经大概了解了json-rpc的东西,那我们接下了看看比特币是怎么转账的

转账功能开发

看了比特币提供的rpc接口,简单的转账分三步走

  1. createrawtransaction
  2. fundrawtransaction
  3. signrawtransaction
  4. sendrawtransaction
  创建签名交易->检查交易费用->签名交易->发送交易
  其中第二部分,如果是个人钱包转账其实不用,我们可以在createrawtransaction设置好交易费用

小明的钱包里面有1个比特币,要将0.5个转账给小李,来吧我们帮他实现,不过小明的1个比特币是从其他地址转入的0.8和0.2个,没关系我们也能帮助他转账

  1. 首先需要先检索小明钱包有0.5个btc没有,我们调用btc提供的getbalance方法
    /**
     * 获取钱包地址余额
     *
     * @return
     */
    public JSONObject getBalance(String address) {
        Object[] params = new Object[3];
        params[0] = address
        params[1] = 6; //这是设置6是确保钱包里面的前都是已经经过区块确认的
        params[2] = true;
        JSONObject jsonObject = null;
        try {
            jsonObject = jsonrpcService.callMethod(BTCMethod.GET_BALANCE.toString(), params, JSONObject.class);
        } catch (Throwable throwable) {
            logger.error("getBalance error", throwable);
        }
        return jsonObject;
    }
  1. 检查小明的钱包的btc是大于0.5个比特币的,那我们接着看他钱包的没有发送的的交易有哪些,这个时候调用btc提供的listunspent 方法
    /**
     * object     {
     "minimumAmount"    (numeric or string, default=0) Minimum value of each UTXO in BTC
     "maximumAmount"    (numeric or string, default=unlimited) Maximum value of each UTXO in BTC
     "maximumCount"     (numeric or string, default=unlimited) Maximum number of UTXOs
     "minimumSumAmount" (numeric or string, default=unlimited) Minimum sum value of all UTXOs in BTC
     }
     * @param minconf
     * @param maxconf
     * @param address
     * @param object
     * @return
     */
    public JSONObject listUnspent(int minconf, int maxconf, List address,Object object)  {
        Object[]  params = new Object[5];
        params[0] = minconf; //最小的金额
        params[1] = maxconf; //最大的金额
        params[2] = address; //地址
        params[3] = true;
        params[4] = object;
        JSONObject jsonObject = null;
        try {
            jsonObject = jsonrpcService.callMethod(BTCMethod.LIST_UNSPENT.toString(), params,JSONObject.class);
        } catch (Throwable throwable) {
            logger.error("listUnspent error",throwable);
        }
        return jsonObject;
    }
  1. 检测夏小明的钱包有两笔unspent,通过返回的txid,和vout,scriptPubKey,amount 我们就可以创建一个createrawtransaction
    //创建的一个输入,txid和vout就是第二步返回的值
    TxInput input = new BTCTranscation.BasicTxInput(us.getTxid(), us.getVout());

    /**
     * 需要设置找零地址信息
     * @param recipientAddress
     * @param amountSend
     * @param sendeAddress
     * @param amountChange
     * @return
     */
    public List createTxOutput(String recipientAddress,BigDecimal amountSend,String sendeAddress,BigDecimal amountChange) {
        List outputs = new ArrayList();
        outputs.add(new BTCTranscation.BasicTxOutput(recipientAddress, getDouble(amountSend))); //设置需要接收的地址和币数量
        outputs.add(new BTCTranscation.BasicTxOutput(sendeAddress, getDouble(amountChange))); //设置需要找零的地址和币数量
        return outputs;
    }

备注:这里记得一定要设置找零地址,因为小明的unsend的交易是0.8个,我们给小李要转0.5个还剩余0.3个,如果不设置找零地址,0.3个就默认都成为矿工费了,找零的币是减去矿工费计算的出来的,我们可以调用btc的 estimatesmartfee方法简单计算矿工费

    /**
     * 获取费率信息
     * @param minconf
     * @return
     */
    public JSONObject estimatesmartfee(int minconf)  {
        Object[]  params = new Object[1];
        params[0] = minconf;
        JSONObject jsonObject = null;
        try {
            jsonObject = jsonrpcService.callMethod(BTCMethod.ESTIMATES_MARTFEE.toString(), params,JSONObject.class);
        } catch (Throwable throwable) {
            logger.error("listUnspent error",throwable);
        }
        return jsonObject;
    }
  1. 创建一笔交易信息,根据我们构造好输入输出,我们创建transaction,这个时候调用btc提供的createrawtransaction方法
 /**
     * 创建交易信息,返回hash 值 ,发送格式:需要计算好找零钱的信息
     *
     * '[{"txid" : "5d2abd13a6ee2d3ffb1758259eb5d0ffece91a86c0670f1e6c472618995a420c", "vout" : 1}]' '{"mj7AFvkxFEvxmGwwP5jgXRtyzhPAhZs2gQ": 0.0005, "my1kprdpM17PZJnB55GwJ5AzLGjx9isHh9": 0.000045}'
     * @param prevOut
     * @param out
     * @return
     */
    public JSONObject createRawTransaction(Object[] prevOut, Object out) {
        Object[]  params = new Object[2];
        params[0] = prevOut;
        params[1] = out;
        JSONObject jsonObject = null;
        try {
            jsonObject = jsonrpcService.callMethod(BTCMethod.CREATE_RAW_TRANSACTION.toString(), params,JSONObject.class);
        } catch (Throwable throwable) {
            logger.error("createRawTransaction error",throwable);
        }
        return jsonObject;
    }

5.加密交易信息,根据上一部返回的hex值,我们进行加密,这个时候调用btc提供的signrawtransaction方法

    /**
     * 交易签名
     * @param hexString
     * @return
     */
    public JSONObject signRawTransaction(String hexString)  {
        Object[] params = new Object[1];
        params[0] = hexString;
        JSONObject jsonObject = null;
        try {
            jsonObject = jsonrpcService.callMethod(BTCMethod.SIGN_RAW_TRANSACTION.toString(), params, JSONObject.class);
        } catch (Throwable throwable) {
            logger.error("signRawTransaction error",throwable);
        }
        return jsonObject;
    }
  1. 小李催着要btc了,那我们赶紧给他发送到btc网络上吧,这个时候调用btc提供的sendrawtransaction方法
    /**
     * 发送签名的交易信息
     *
     * @param hexString
     * @return
     */
    public JSONObject sendRawTransaction(String hexString)  {
        Object[] params = new Object[1];
        params[0] = hexString;
        JSONObject jsonObject = null;
        try {
            jsonObject = jsonrpcService.callMethod(BTCMethod.SEND_RAW_TRANSACTION.toString(), params, JSONObject.class);
        } catch (Throwable throwable) {
            logger.error("sendRawTransaction error",throwable);
        }
        return jsonObject;
    }

返回了一个hex值:xxxxxxxx,给小李,让他可以在区块浏览器上查看转账进度了

后续

这里只是简单的开发了一个比特币转账的流程,具体实际中可能会遇到各种问题,尤其是矿工费计算之类的;如果是交易所之类的转账,应该基本上都是签名和发送都是隔离的,因为签名不需要网络,只需要账户的私钥。流程上搞懂了,其实感觉也没有那么复杂,测试的时候直接用的是本地搭建的btc网络节点测试整个流程。

你可能感兴趣的:(比特币转账功能开发)