bitcoinjs教程
在这个教程中,我们将学习如何使用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 = 'aaa@qq.com'
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()
函数,我们就可以在任何时候用aaa@qq.com
这个密码来会付出地址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('aaa@qq.com')
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('aaa@qq.com')
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.
上一篇: 数独游戏(回溯算法)