您好,登錄后才能下訂單哦!
用JavaScript開發(fā)比特幣應(yīng)用BitcoinJS-lib的過程是怎樣的,相信很多沒有經(jīng)驗(yàn)的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
在這個(gè)教程中,我們將學(xué)習(xí)如何使用Bitconjs-lib開發(fā)庫來開發(fā)一個(gè)簡單的JavaScript版本的比特幣應(yīng)用。我們要實(shí)現(xiàn)的特性包括:離線創(chuàng)建比特幣私鑰和地址、進(jìn)行賬戶充值、離線構(gòu)造轉(zhuǎn)賬裸交易并廣播到比特幣網(wǎng)絡(luò)中等。
BitcoinJS-lib是一個(gè)npm包,可以用于node.js或?yàn)g覽器javascript環(huán)境中??梢允褂胣pm或yarn安裝BitcoinJS-lib開發(fā)包:
npm install bitcoinjs-lib
首先引入bitcoinjs-lib開發(fā)庫:
const Btc = require('bitcoinjs-lib')
比特幣的主鏈和測試鏈有不同的網(wǎng)絡(luò)參數(shù),出于簡化和安全性考慮,我們使用測試鏈來開發(fā)這個(gè)教程中的應(yīng)用,因此引入測試鏈網(wǎng)絡(luò)參數(shù):
const TestNet = Btc.networks.testnet
每個(gè)比特幣地址都對應(yīng)一對密鑰(私鑰和公鑰),因此我們首先用BitcoinJS創(chuàng)建密鑰對并從密鑰對推導(dǎo)出地址:
let keyPair = Btc.ECPair.makeRandom({ network: TestNet }) let address = keyPair.getAddress() let wifKey = keyPair.toWIF() console.log(`Address: ${address} \n WifKey: ${wifKey}`)
在上邊的代碼中,我們首先使用BitcoinJS的ECPair
類的靜態(tài)方法makeRandom()
生成一個(gè)隨機(jī)密鑰對,然后使用密鑰對的getAddress()
方法推導(dǎo)出對應(yīng)的比特幣地址,并使用toWif()
獲取WIF格式的私鑰,最后顯示出得到的地址和WIF格式的私鑰。
代碼運(yùn)行結(jié)果如下(你的結(jié)果應(yīng)該與此不同):
Address: mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1 WifKey: cTEAh3DsC7KE4mzY5YFTYommzr7czbdiBfLPsXZrF6o3zSQLLw9Q
如果你有其他錢包到處的WIF格式的私鑰,也可以導(dǎo)入BitcoinJS并推導(dǎo)出對應(yīng)的地址,例如:
let wifKey = 'cTEAh3DsC7KE4mzY5YFTYommzr7czbdiBfLPsXZrF6o3zSQLLw9Q' let keyPair = new Btc.ECPair.fromWIF(privKey, TestNet) console.log("Address:", keyPair.getAddress())
結(jié)果類似如下:
Address: mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1
要記住私鑰有點(diǎn)麻煩,我們可以用密碼來輔助推導(dǎo)私鑰,這樣就可以進(jìn)一步推導(dǎo)出公鑰和地址。下面的代碼使用BitcoinJS和nodejs大數(shù)計(jì)算庫bigi實(shí)現(xiàn):
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; }
結(jié)果如下:
Address: mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1
現(xiàn)在使用generateAddressFromSHA256Hash()
函數(shù),我們就可以在任何時(shí)候用J@VaSc1pt
這個(gè)密碼來會(huì)付出地址mqVKYrNJcMkdK2QHFNEd1P6Qfc1Sqs3hu1
以及其對應(yīng)的密鑰對了。
在繼續(xù)之前,我們需要為創(chuàng)建的比特幣地址充點(diǎn)比特幣。在網(wǎng)上有一些比特幣測試鏈的Faucet,可以用來為任意指定的比特幣地址充入一些比特幣以便進(jìn)行開發(fā)和測試。我使用的是這個(gè),當(dāng)然你可以搜索出更多的這種Faucet。
讓Faucet給我們的測試地址充值結(jié)果如下:
cool,現(xiàn)在我們有了1.3個(gè)比特幣可以繼續(xù)測試了!
有兩種辦法查詢一個(gè)比特幣地址的余額、UTXO等信息:使用自己的節(jié)點(diǎn),或者使用第三方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)) } );
結(jié)果如下:
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
構(gòu)造比特幣裸交易要復(fù)雜一點(diǎn),我們需要自己組織交易的輸入和輸出。
首先用BitcoinJS的交易構(gòu)造器TransactionBuider
創(chuàng)建一個(gè)交易對象:
let tx = new Btc.TransactionBuilder(TestNet)
然后我們聲明轉(zhuǎn)出賬號(hào)和轉(zhuǎn)入賬號(hào):
let keyPair1 = generateAddressFromSHA256Hash('J@vaScr1pt') let keyPair2 = generateAddressFromSHA256Hash('B*tc0in')
然后聲明轉(zhuǎn)賬金額、手續(xù)費(fèi)等參數(shù),并計(jì)算找零金額:
let amountWeHave = 130000000 // 1.3 BTC let amountToKeep = 100000000 // 1 BTC let transactionFee = 1000 // .00001 BTC let amountToSend = amountWeHave - amountToKeep - transactionFee
好了,現(xiàn)在可以為交易添加輸入了。還記得前面我們查詢出來的交易輸出嗎?這個(gè)交易輸出我們將用作新交易的輸入:
[{ txid: '2d742aa8409ee4cd8afcb2f59aac6ede47b478fafbca2335c9c04c6aedf94c9b', vout: 0, satoshis: 130000000, }]
使用BitcoinJS交易對象的addInput()
方法添加交易輸入:
tx.addInput('2d742aa8409...', 0)
接下來添加交易輸出,我們需要聲明交易輸出目標(biāo)地址和金額:
tx.addOutput(keyPair2.getAddress(), amountToSend)
由于交易輸入金額大于上述交易輸出金額,因此我們還需要添加找零輸出:
tx.addOutput(keyPair1.getAddress(), amountToKeep)
現(xiàn)在我們進(jìn)行簽名,由于用的是keyPair1的比特幣,因此需要使用keyPair1的私鑰進(jìn)行簽名:
tx.sign(0, keyPair1)
接下來把簽名交易序列化為16進(jìn)制碼流,以便廣播到比特幣網(wǎng)絡(luò)中:
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)
輸出結(jié)果如下:
01000000019b4cf9ed6a4cc0c93523cafbfa78b447de6eac9af5b2fc8acde49e40 a82a742d000000006b483045022100b8e1bc891bbd910960cf00b52b87493ddf80 8c0b6816b05724b62c507c2ea552022071d775d9b89e0bbc1c2d1b907b700dbda5 8d880508ba7f6e11a3acc659d3ebe20121034ec9060d1935b235794e22f5335b4e 5c55e764ba9bddab2cf7f199dac7309ce1ffffffff0298bfc901000000001976a9 1423e6e135110f5fcacbd77323382bb70e4f76105f88ac00e1f505000000001976 a9146d622b371423d2e450c19d98059867d71e6aa87c88ac00000000
在廣播裸交易之前,檢查一下裸交易的內(nèi)容是一種有效的調(diào)試方法。我們可以使用BlockCypher提供的解碼工具來查看裸交易的內(nèi)容,結(jié)果如下
{ "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 }
一旦生成比特幣裸交易,可以在網(wǎng)上找到很多提供廣播比特幣裸交易的服務(wù)。如果你希望在代碼中進(jìn)行廣播,也可以使用這個(gè)API。
廣播完成后,你可以在區(qū)塊瀏覽器中查看交易確認(rèn)情況:
看完上述內(nèi)容,你們掌握用JavaScript開發(fā)比特幣應(yīng)用BitcoinJS-lib的過程是怎樣的的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。