nodejs與btc網(wǎng)絡交互使用
bitcoinjs-lib
模組
使用BTC測試網(wǎng)進行測試
安裝模組
npm i bitcoinjs-lib
根據(jù)隨機字符構造兩個函數(shù)
function rng () { return Buffer.from('tmd123zzzzzzzzzzzzzzzzzzzzzzzzzz') }
function rng2 () { return Buffer.from('tmd321333zzzzzzzzzzzzzzzzzzzzzzz') }
生成錢包1媒至, 指定測試鏈
const alice = bitcoin.ECPair.makeRandom({network: testnet, rng});
const { address } = bitcoin.payments.p2pkh({ pubkey: alice.publicKey, network: testnet });
// console.log(address);
// console.log(alice.toWIF())
// 地址: mmH6e8tfLyvrrnFF3o1scaNsPXShGY89rb
// 私鑰: L182iNrxy9rSPQfEg5X1P1sR9qAbS1pbxPosguD8Sx5tYauV3bYm
生成錢包2
const bob = bitcoin.ECPair.makeRandom({network: testnet, rng: rng2 });
const { address:address2 } = bitcoin.payments.p2pkh({ pubkey: bob.publicKey, network: testnet });
// console.log(address2);
// console.log(bob.toWIF())
// 地址: miAMpCdoM3SuRMRoEVHp8smFdDAz29WA9g
// 私鑰: L182iNub4Z8Ly6H13jcx7i82jKq3czc7WzFso3z249LuMcMjzQXo
- 比特幣轉賬需要提取或合并所有未花費的交易中的比特幣蹋艺,才能實現(xiàn)交易厘熟。
- 描述起來比較復雜脚线,下圖是個例子屎媳,我們從區(qū)塊瀏覽器查到我最近一筆未花費支出脖捻,某個地址轉了0.03個BTC給我,在這一筆交易中阔逼,我有0.03個BTC。
-
如果我要轉出0.5個BTC給他人地沮,我需要合并其他的交易嗜浮,否則將會余額不足,雖然在我這個地址中有足夠的BTC摩疑。
單個哈希交易危融。
const transfer1 = async () => {
// 注意要指定交易對象是測試鏈的
const txb = new bitcoin.TransactionBuilder(testnet);
txb.setVersion(1);
// 在這個交易中, bob在第0個位置雷袋,上圖所示
txb.addInput('5799a647d6b89a9f73122d75faee6f5a0210bd3cb22c48a70d35eac33ce5d426', 0);
// 這里把btc轉給 alice 的地址吉殃,金額是0.02 但是要*100000000, 也就是2000000,
// 剩余的金額沒有設置招零地址接收,則被視為手續(xù)費楷怒,被區(qū)塊網(wǎng)絡收取
// 每一筆交易只有已花費和未花費兩種狀態(tài)蛋勺,不存在消費一部分的狀態(tài),
// 所以合并多筆交易的話率寡,只要未花費迫卢,都可以合并。
txb.addOutput('mmH6e8tfLyvrrnFF3o1scaNsPXShGY89rb', 2000000);
// 簽名交易冶共,0代表索引乾蛤,輸入排序每界,這里只有一個輸入,所以是第0位家卖。
txb.sign(0, bob);
// 序列化成一串字符
const tx = txb.build().toHex();
console.log(tx);
// 在一個測試鏈的節(jié)點把交易廣布出去
const result = await fetch('https://api.blockcypher.com/v1/btc/test3/txs/push',{
method:'post',
headers:{'Content-Type':'application/json'},
body:JSON.stringify({tx})
});
// 打印結果
console.log(result);
};
transfer1();
- 轉賬的時候需要手動尋找每一筆未花費記錄實在太費時眨层。
- 所以需要一個輔助節(jié)點來提取未來花費的記錄
- 以下是一個區(qū)塊瀏覽器的鏈接,可以查詢到索要的記錄
https://api.blockcypher.com/v1/btc/test3/addrs/miAMpCdoM3SuRMRoEVHp8smFdDAz29WA9g
多筆交易上荡,自動合并趴樱。
const transfer2 = async () => {
const url = 'https://api.blockcypher.com/v1/btc/test3/addrs/';
const res = await fetch(url+address2);
const json = await res.json();
const balance = json.balance;
// console.log(balance/100000000);
const txrefs = json.txrefs;
// 過濾掉已經(jīng)被花費了的交易,以及自己不在接收列表的交易
const unspentList = txrefs.filter(item=> !item.spent_by && item.tx_output_n !== -1);
// 這個地址還可以查詢余額
// console.log(unspentList);
// 構建交易對象
const txb = new bitcoin.TransactionBuilder(testnet);
txb.setVersion(1);
// 批量插入未花費交易
unspentList.forEach(item=>txb.addInput(item.tx_hash, item.tx_output_n));
// 轉出賬戶
txb.addOutput('mmH6e8tfLyvrrnFF3o1scaNsPXShGY89rb', 2000000);
// 設置找零地址酪捡,如果忘記了叁征,就會丟失所有BTC !9滢薄^嗵邸!S婪!F『簟!呢袱!
// 如果不預留手續(xù)費官扣,交易可能會一直不被打包!
// 3000 為手續(xù)費
txb.addOutput('miAMpCdoM3SuRMRoEVHp8smFdDAz29WA9g',balance - 2000000 - 3000);
// 批量簽名羞福,根據(jù)索引即可
unspentList.forEach((item,index)=>{txb.sign(index, bob)});
// 序列化交易
const tx = txb.build().toHex();
// console.log(tx);
// 在一個測試鏈的節(jié)點把交易廣布出去
const result = await fetch('https://api.blockcypher.com/v1/btc/test3/txs/push',{
method:'post',
headers:{'Content-Type':'application/json'},
body:JSON.stringify({tx})
});
// 打印結果
console.log(result);
};
transfer2();