nodejs調(diào)用bitcoin轉(zhuǎn)賬功能

nodejs與btc網(wǎng)絡(luò)交互使用bitcoinjs-lib模組
使用BTC測(cè)試網(wǎng)進(jìn)行測(cè)試

安裝模組

npm i bitcoinjs-lib

根據(jù)隨機(jī)字符構(gòu)造兩個(gè)函數(shù)

function rng () { return Buffer.from('tmd123zzzzzzzzzzzzzzzzzzzzzzzzzz') }
function rng2 () { return Buffer.from('tmd321333zzzzzzzzzzzzzzzzzzzzzzz') }

生成錢(qián)包1, 指定測(cè)試鏈

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

生成錢(qián)包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
  • 比特幣轉(zhuǎn)賬需要提取或合并所有未花費(fèi)的交易中的比特幣,才能實(shí)現(xiàn)交易。
  • 描述起來(lái)比較復(fù)雜,下圖是個(gè)例子,我們從區(qū)塊瀏覽器查到我最近一筆未花費(fèi)支出,某個(gè)地址轉(zhuǎn)了0.03個(gè)BTC給我,在這一筆交易中,我有0.03個(gè)BTC。
  • 如果我要轉(zhuǎn)出0.5個(gè)BTC給他人,我需要合并其他的交易,否則將會(huì)余額不足,雖然在我這個(gè)地址中有足夠的BTC。


    1.png

    2.png
單個(gè)哈希交易。
const transfer1 = async () => {

  // 注意要指定交易對(duì)象是測(cè)試鏈的
  const txb = new bitcoin.TransactionBuilder(testnet);
  txb.setVersion(1);
  // 在這個(gè)交易中, bob在第0個(gè)位置,上圖所示
  txb.addInput('5799a647d6b89a9f73122d75faee6f5a0210bd3cb22c48a70d35eac33ce5d426', 0);
  
  // 這里把btc轉(zhuǎn)給 alice 的地址,金額是0.02 但是要*100000000, 也就是2000000,
  // 剩余的金額沒(méi)有設(shè)置招零地址接收,則被視為手續(xù)費(fèi),被區(qū)塊網(wǎng)絡(luò)收取
  // 每一筆交易只有已花費(fèi)和未花費(fèi)兩種狀態(tài),不存在消費(fèi)一部分的狀態(tài),
  // 所以合并多筆交易的話,只要未花費(fèi),都可以合并。
  txb.addOutput('mmH6e8tfLyvrrnFF3o1scaNsPXShGY89rb', 2000000);

  // 簽名交易,0代表索引,輸入排序,這里只有一個(gè)輸入,所以是第0位。
  txb.sign(0, bob);

  // 序列化成一串字符
  const tx = txb.build().toHex();
  console.log(tx);

  // 在一個(gè)測(cè)試鏈的節(jié)點(diǎn)把交易廣布出去
  const result = await fetch('https://api.blockcypher.com/v1/btc/test3/txs/push',{
    method:'post',
    headers:{'Content-Type':'application/json'},
    body:JSON.stringify({tx})
  });

  // 打印結(jié)果
  console.log(result);
};

transfer1();
多筆交易,自動(dòng)合并。
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;

  // 過(guò)濾掉已經(jīng)被花費(fèi)了的交易,以及自己不在接收列表的交易
  const unspentList = txrefs.filter(item=> !item.spent_by && item.tx_output_n !== -1);
  // 這個(gè)地址還可以查詢(xún)余額
  // console.log(unspentList);

  // 構(gòu)建交易對(duì)象
  const txb = new bitcoin.TransactionBuilder(testnet);
  txb.setVersion(1);

  // 批量插入未花費(fèi)交易
  unspentList.forEach(item=>txb.addInput(item.tx_hash, item.tx_output_n));

  // 轉(zhuǎn)出賬戶
  txb.addOutput('mmH6e8tfLyvrrnFF3o1scaNsPXShGY89rb', 2000000);

  // 設(shè)置找零地址,如果忘記了,就會(huì)丟失所有BTC !?。。。。。?!
  // 如果不預(yù)留手續(xù)費(fèi),交易可能會(huì)一直不被打包!
 // 3000 為手續(xù)費(fèi)
  txb.addOutput('miAMpCdoM3SuRMRoEVHp8smFdDAz29WA9g',balance - 2000000 - 3000);
  
  // 批量簽名,根據(jù)索引即可
  unspentList.forEach((item,index)=>{txb.sign(index, bob)});

  // 序列化交易
  const tx = txb.build().toHex();
  // console.log(tx);

  // 在一個(gè)測(cè)試鏈的節(jié)點(diǎn)把交易廣布出去
  const result = await fetch('https://api.blockcypher.com/v1/btc/test3/txs/push',{
    method:'post',
    headers:{'Content-Type':'application/json'},
    body:JSON.stringify({tx})
  });

  // 打印結(jié)果
  console.log(result);


};

transfer2();

全部代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容