废话不多说,说了你们也不看,直接上代码吧
maven依赖
<!-- https://mvnrepository.com/artifact/org.bitcoinj/bitcoinj-core -->
<dependency>
<groupId>org.bitcoinj</groupId>
<artifactId>bitcoinj-core</artifactId>
<version>0.15.8</version>
</dependency>
生成地址,私钥 ,公钥以及助记词
/**
* 创建钱包地址
*
* @return
*/
public static Map newaddress() {
NetworkParameters networkParameters = MainNetParams.get() ;
DeterministicSeed seed = new DeterministicSeed(new SecureRandom(), 128, "", Utils.currentTimeSeconds());
Wallet wallet;
String mnemonics = "";
String privateKey = "";
String publicKey = "";
String address = "";
String pwd = "";
try {
wallet = Wallet.fromSeed(networkParameters, seed);
//私钥
privateKey = wallet.currentReceiveKey().getPrivateKeyAsWiF(networkParameters);
//助记词
mnemonics = wallet.getKeyChainSeed().getMnemonicCode().toString();
publicKey = Hex.toHexString(ECKey.publicKeyFromPrivate(wallet.currentReceiveKey().getPrivKey(), true));
//地址
address = wallet.currentReceiveAddress().toBase58();
} catch (Exception e) {
logger.error("比特币地址创建失败,原因"+e);
return null;
}
Map resultMap = new LinkedHashMap();
resultMap.put("mnemonics", mnemonics);
resultMap.put("privateKey", privateKey);
resultMap.put("publicKey", publicKey);
resultMap.put("address", address);
return resultMap;
}
获取余额
public static double getBalance(String address){
double balance = 0.0 ;
try {
String url = "https://chain.api.btc.com/v3/address/" + address;
String request = HttpUtils.getRequest(url);
JSONObject data = JSONObject.parseObject(request);
JSONObject jsonObject = data.getJSONObject("data");
Double bal = jsonObject.getDouble("balance");
return bal ;
}catch (Exception e){
return 0.0 ;
}
}
获取未消费地址(utxo)
/***
* 获取未消费列表
* @param address :地址
* @return
*/
public static List<UTXO> getUnspent(String address) {
List<UTXO> utxos = Lists.newArrayList();
String host = isMainNet ? "blockchain.info" : "testnet.blockchain.info";
String url = "https://insight.bitpay.com/api/addr/"+address+"/utxo";
try {
String httpGet = HttpUtils.getRequest(url, null);//
if (StringUtils.equals("No free outputs to spend", httpGet)) {
return utxos;
}
JSONArray unspentOutputs = JSONObject.parseArray(httpGet) ;
List<Map> outputs = JSONObject.parseArray(unspentOutputs.toJSONString(), Map.class);
if (outputs == null || outputs.size() == 0) {
System.out.println("交易异常,余额不足");
}
for (int i = 0; i < outputs.size(); i++) {
Map outputsMap = outputs.get(i);
String address2 = outputsMap.get("address").toString();
String tx_hash = outputsMap.get("txid").toString();
String tx_output_n = outputsMap.get("vout").toString();
String script = outputsMap.get("scriptPubKey").toString();
String value = outputsMap.get("height").toString();
UTXO utxo = new UTXO(Sha256Hash.wrap(tx_hash), Long.valueOf(tx_output_n), Coin.valueOf(Long.valueOf(value)),
0, false, new Script(Hex.decode(script)));
utxos.add(utxo);
}
return utxos;
} catch (Exception e) {
logger.error("【BTC获取未消费列表】失败,"+ e);
return null;
}
}
获取btc费率
/**
* 获取btc费率
*
* @return
*/
public static Long getFeeRate() {
try {
String httpGet1 = HttpUtils.getRequest("https://bitcoinfees.earn.com/api/v1/fees/recommended", null);
Map map = JSON.parseObject(httpGet1, Map.class);
Long fastestFee = Long.valueOf(map.get("fastestFee").toString());
return fastestFee;
} catch (Exception e) {
e.printStackTrace();
return 0L;
}
}
获取旷工费用
/**
* 获取矿工费用
* @param amount
* @param utxos
* @return
*/
public static Long getFee(long amount, List<UTXO> utxos) {
Long feeRate = getFeeRate();//获取费率
Long utxoAmount = 0L;
Long fee = 0L;
Long utxoSize = 0L;
for (UTXO us : utxos) {
utxoSize++;
if (utxoAmount >= (amount + fee)) {
break;
} else {
utxoAmount += us.getValue().value;
fee = (utxoSize * 148 * 34 + 10) * feeRate;
}
}
return fee;
}
离线签名
/**
* btc交易签名
* @param fromAddress
* @param toAddress
* @param privateKey
* @param amount
* @param fee
* @param utxos
* @return
* @throws Exception
*/
public static String sign(String fromAddress, String toAddress, String privateKey, long amount, long fee, List<UTXO> utxos) throws Exception {
NetworkParameters networkParameters = isMainNet ? MainNetParams.get() : TestNet3Params.get();
Transaction transaction = new Transaction(networkParameters);
String changeAddress = fromAddress;//找零地址
Long changeAmount = 0L;
Long utxoAmount = 0L;
List<UTXO> needUtxos = new ArrayList<UTXO>();
//获取未消费列表
if (utxos == null || utxos.size() == 0) {
throw new Exception("未消费列表为空");
}
//遍历未花费列表,组装合适的item
for (UTXO utxo : utxos) {
if (utxoAmount >= (amount + fee)) {
break;
} else {
needUtxos.add(utxo);
utxoAmount += utxo.getValue().value;
}
}
transaction.addOutput(Coin.valueOf(amount), Address.fromBase58(networkParameters, toAddress));
//消费列表总金额 - 已经转账的金额 - 手续费 就等于需要返回给自己的金额了
changeAmount = utxoAmount - (amount + fee);
//余额判断
if (changeAmount < 0) {
throw new Exception("utxo余额不足");
}
//输出-转给自己(找零)
if (changeAmount > 0) {
transaction.addOutput(Coin.valueOf(changeAmount), Address.fromBase58(networkParameters, changeAddress));
}
//输入未消费列表项
DumpedPrivateKey dumpedPrivateKey = DumpedPrivateKey.fromBase58(networkParameters, privateKey);
ECKey ecKey = dumpedPrivateKey.getKey();
for (UTXO utxo : needUtxos) {
TransactionOutPoint outPoint = new TransactionOutPoint(networkParameters, utxo.getIndex(), utxo.getHash());
transaction.addSignedInput(outPoint, utxo.getScript(), ecKey, Transaction.SigHash.ALL, true);
}
byte[] bytes = transaction.bitcoinSerialize();
String hash = Hex.toHexString(transaction.bitcoinSerialize());
logger.info("fee:{},utxoAmount:{},changeAmount{}", fee, utxoAmount, changeAmount);
return hash;
}
广播交易
public static String publishTx(String Hash){
HashMap<String, String> map = Maps.newHashMap();
map.put("rawhex",Hash) ;
String jsonObject = HttpsUtils.sendPost("https://chain.api.btc.com/v3//tools/tx-publish", map);
return jsonObject ;
}
如果帮助到你,请点点关注,谢谢