在這個教程中,我們将學習如何使用Bitconjs-lib開發庫來開發一個簡單的JavaScript版本的比特币應用。我們要實作的特性包括:離線建立比特币私鑰和位址、進行賬戶充值、離線構造轉賬裸交易并廣播到比特币網絡中等。
Node.js區塊鍊開發相關教程推薦:
1、安裝BitcoinJS-lib
BitcoinJS-lib是一個npm包,可以用于node.js或浏覽器javascript環境中。可以使用npm或yarn安裝BitcoinJS-lib開發包:
npm install bitcoinjs-lib
2、引入BitcoinJS-lib
首先引入bitcoinjs-lib開發庫:
const Btc = require('bitcoinjs-lib')
比特币的主鍊和測試鍊有不同的網絡參數,出于簡化和安全性考慮,我們使用測試鍊來開發這個教程中的應用,是以引入測試鍊網絡參數:
const TestNet = Btc.networks.testnet
3、用BitcoinJS建立比特币位址
每個比特币位址都對應一對密鑰(私鑰和公鑰),是以我們首先用BitcoinJS建立密鑰對并從密鑰對推導出位址:
let keyPair = Btc.ECPair.makeRandom({ network: TestNet })
let address = keyPair.getAddress()
let wifKey = keyPair.toWIF()
console.log(`Address: ${address} \n WifKey: ${wifKey}`)
在上邊的代碼中,我們首先使用BitcoinJS的
ECPair
類的靜态方法
makeRandom()
生成一個随機密鑰對,然後使用密鑰對的
getAddress()
方法推導出對應的比特币位址,并使用
toWif()
擷取WIF格式的私鑰,最後顯示出得到的位址和WIF格式的私鑰。
代碼運作結果如下(你的結果應該與此不同):
Address: mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1
WifKey: cTEAh2DsC7KE4mzY5YFTYommzr7czbdiBfLPsXZrF6o3zSQLLw9Q
4、用BitcoinJS導入WIF私鑰
如果你有其他錢包到處的WIF格式的私鑰,也可以導入BitcoinJS并推導出對應的位址,例如:
let wifKey = 'cTEAh2DsC7KE4mzY5YFTYommzr7czbdiBfLPsXZrF6o3zSQLLw9Q'
let keyPair = new Btc.ECPair.fromWIF(privKey, TestNet)
console.log("Address:", keyPair.getAddress())
結果類似如下:
Address: mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1
5、使用密碼輔助記憶私鑰
要記住私鑰有點麻煩,我們可以用密碼來輔助推導私鑰,這樣就可以進一步推導出公鑰和位址。下面的代碼使用BitcoinJS和nodejs大數計算庫bigi實作:
const BigInteger = require('bigi')
let passphrase = 'J@vaScr1pt'
let keyPair = generateAddressFromSHA256Hash(passphrase);
console.log('Address: ', keyPair.getAddress())
function generateAddressFromSHA256Hash(passphrase) {
let hash = Btc.crypto.sha256(passphrase);
let d = BigInteger.fromBuffer(hash);
let keyPair = new Btc.ECPair(d, null, { network: TestNet });
return keyPair;
}
結果如下:
Address: mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1
現在使用
generateAddressFromSHA256Hash()
函數,我們就可以在任何時候用
J@VaSc1pt
這個密碼來會付出位址
mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1
以及其對應的密鑰對了。
6、使用測試鍊Faucet為賬戶充值
在繼續之前,我們需要為建立的比特币位址充點比特币。在網上有一些比特币測試鍊的Faucet,可以用來為任意指定的比特币位址充入一些比特币以便進行開發和測試。我使用的是
這個,當然你可以搜尋出更多的這種Faucet。
讓Faucet給我們的測試位址充值結果如下:

cool,現在我們有了1.3個比特币可以繼續測試了!
7、查詢比特币位址詳情
有兩種辦法查詢一個比特币位址的餘額、UTXO等資訊:使用自己的節點,或者使用第三方API。出于簡化考慮,在本教程中我們使用第三方API來查詢指定比特币位址的餘額與UTXO:
onst request = require('request');
let addr = 'mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1'
let apiUrl = 'https://testnet.blockexplorer.com/api/addr/'
// log unspent transactions
request.get(apiUrl + addr + '/utxo', (err, req, body) => {
console.log('utxo => ', JSON.parse(body))
}
);
// log balance
request.get(apiUrl + addr + '/balance', (err, req, body) => {
console.log('balance => ', JSON.parse(body))
}
);
utxo => [{
address: 'mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1',
txid: '2d742aa8409ee4cd8afcb2f59aac6ede47b478fafbca2335c9c04c6aedf94c9b',
vout: 0,
scriptPubKey: '76a9146d622b371423d2e450c19d98059867d71e6aa87c88ac',
amount: 1.3,
satoshis: 130000000,
height: 1180957,
confirmations: 14
}]
balance => 130000000 // 1.3 BTC = 130000000 satoshis
8、用BitcoinJS構造比特币轉賬裸交易
構造比特币裸交易要複雜一點,我們需要自己組織交易的輸入和輸出。
首先用BitcoinJS的交易構造器
TransactionBuider
建立一個交易對象:
let tx = new Btc.TransactionBuilder(TestNet)
然後我們聲明轉出賬号和轉入賬号:
let keyPair1 = generateAddressFromSHA256Hash('J@vaScr1pt')
let keyPair2 = generateAddressFromSHA256Hash('B*tc0in')
然後聲明轉賬金額、手續費等參數,并計算找零金額:
let amountWeHave = 130000000 // 1.3 BTC
let amountToKeep = 100000000 // 1 BTC
let transactionFee = 1000 // .00001 BTC
let amountToSend = amountWeHave - amountToKeep - transactionFee
好了,現在可以為交易添加輸入了。還記得前面我們查詢出來的交易輸出嗎?這個交易輸出我們将用作新交易的輸入:
[{
txid: '2d742aa8409ee4cd8afcb2f59aac6ede47b478fafbca2335c9c04c6aedf94c9b',
vout: 0,
satoshis: 130000000,
}]
使用BitcoinJS交易對象的
addInput()
方法添加交易輸入:
tx.addInput('2d742aa8409...', 0)
接下來添加交易輸出,我們需要聲明交易輸出目标位址和金額:
tx.addOutput(keyPair2.getAddress(), amountToSend)
由于交易輸入金額大于上述交易輸出金額,是以我們還需要添加找零輸出:
tx.addOutput(keyPair1.getAddress(), amountToKeep)
現在我們進行簽名,由于用的是keyPair1的比特币,是以需要使用keyPair1的私鑰進行簽名:
tx.sign(0, keyPair1)
接下來把簽名交易序列化為16進制碼流,以便廣播到比特币網絡中:
let tx_hex = tx.build().toHex()
完整的代碼如下:
let tx = new Btc.TransactionBuilder(TestNet)
let keyPair1 = generateAddressFromSHA256Hash('J@vaScr1pt')
let keyPair2 = generateAddressFromSHA256Hash('B*tc0in')
let amountWeHave = 130000000 // 1.3 BTC
let amountToKeep = 100000000 // 1 BTC
let transactionFee = 1000 // .00001 BTC
let amountToSend = amountWeHave - amountToKeep - transactionFee
tx.addInput('2d742aa8409ee4cd8afcb2f59aac6ede47b478fafbca2335c9c04c6aedf94c9b', 0)
tx.addOutput(keyPair2.getAddress(), amountToSend)
tx.addOutput(keyPair1.getAddress(), amountToKeep)
tx.sign(0, keyPair1)
let tx_hex = tx.build().toHex()console.log('our beautiful transaction: ', tx_hex)
輸出結果如下:
01000000019b4cf9ed6a4cc0c93523cafbfa78b447de6eac9af5b2fc8acde49e40
a82a742d000000006b483045022100b8e1bc891bbd910960cf00b52b87493ddf80
8c0b6816b05724b62c507c2ea552022071d775d9b89e0bbc1c2d1b907b700dbda5
8d880508ba7f6e11a3acc659d3ebe20121034ec9060d1935b235794e22f5335b4e
5c55e764ba9bddab2cf7f199dac7309ce1ffffffff0298bfc901000000001976a9
1423e6e135110f5fcacbd77323382bb70e4f76105f88ac00e1f505000000001976
a9146d622b371423d2e450c19d98059867d71e6aa87c88ac00000000
9、解碼裸交易
在廣播裸交易之前,檢查一下裸交易的内容是一種有效的調試方法。我們可以使用BlockCypher提供的
解碼工具來檢視裸交易的内容,結果如下
{
"addresses": [
"mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1",
"minnXa8Qarg5WbxPQg3vjLZdpbZGHavCzC"
],
"block_height": -1,
"block_index": -1,
"confirmations": 0,
"double_spend": false,
"fees": 1000,
"hash": "64697ab2a3c76b8c5930ca128316238bba5b172b2f8f61a0046b6630b1f80f08",
"inputs": [
{
"addresses": [
"mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1"
],
"age": 1180957,
"output_index": 0,
"output_value": 130000000,
"prev_hash": "2d742aa8409ee4cd8afcb2f59aac6ede47b478fafbca2335c9c04c6aedf94c9b",
"script": "483045022100b8e1bc891bbd910960cf00b52b87493ddf808c0b6816b05724b62c507c2ea552022071d775d9b89e0bbc1c2d1b907b700dbda58d880508ba7f6e11a3acc659d3ebe20121034ec9060d1935b235794e22f5335b4e5c55e764ba9bddab2cf7f199dac7309ce1",
"script_type": "pay-to-pubkey-hash",
"sequence": 4294967295
}
],
"outputs": [
{
"addresses": [
"minnXa8Qarg5WbxPQg3vjLZdpbZGHavCzC"
],
"script": "76a91423e6e135110f5fcacbd77323382bb70e4f76105f88ac",
"script_type": "pay-to-pubkey-hash",
"value": 29999000
},
{
"addresses": [
"mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1"
],
"script": "76a9146d622b371423d2e450c19d98059867d71e6aa87c88ac",
"script_type": "pay-to-pubkey-hash",
"value": 100000000
}
],
"preference": "low",
"received": "2017-09-04T05:24:14.417939071Z",
"relayed_by": "54.158.194.253",
"size": 226,
"total": 129999000,
"ver": 1,
"vin_sz": 1,
"vout_sz": 2
}
10、廣播比特币裸交易
一旦生成比特币裸交易,可以在網上找到很多提供廣播比特币裸交易的服務。如果你希望在代碼中進行廣播,也可以使用
這個API。
廣播完成後,你可以在區塊浏覽器中檢視交易确認情況:
DONE.
原文連結:
Bitcoinjs-lib比特币開發簡明教程 - 彙智網