欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

用bsv.js和MatterCloud实现可以收发比特币BSV的极简钱包

程序员文章站 2022-05-21 17:47:59
...

这篇文章教大家如何自己编写一个极简的BSV钱包,可以生成私钥、地址,并发送交易。

 

准备工作

语言:JavaScript

环境:Node.js

操作系统:Win、Mac、Linux

推荐IDE:VSCode

 

首先,确保计算机上安装了Node.js并配置了环境变量,如果没有安装Node.js,可以到官网(https://nodejs.org/zh-cn/)下载安装。

 

新建一个工程文件夹,名字任意,例如SimplestWallet。用命令行打开这个文件夹。

用bsv.js和MatterCloud实现可以收发比特币BSV的极简钱包

依次输入如下命令安装所需的依赖包:

npm install bsv
npm install mattercloudjs

如果看到如下log,说明依赖包安装成功(版本号不一样没关系)。

...
+ aaa@qq.com
...
+ aaa@qq.com
...

其中,bsv库(https://docs.moneybutton.com/docs/bsv-overview.html)是用于比特币BSV的事务数据操作方法的库。

mattercloudjs库(https://www.mattercloud.net)封装了和比特币运营节点MatterCloud通信的网络API。

 

然后,我们需要申请一下MatterCloud的免费API权限。到官网(https://www.mattercloud.net)点击 `Get API Key` 按钮,

用bsv.js和MatterCloud实现可以收发比特币BSV的极简钱包

再点击Generate,即可得到Key。

 

用bsv.js和MatterCloud实现可以收发比特币BSV的极简钱包

 

生成私钥和地址

在制作钱包之前,我们先随机生成一个私钥。我们当然可以手动打入随机数,但正常做法是用随机算法生成,这样可以保证编码正确。

创建一个random-key.js文件,代码如下

const BSV = require('bsv') //引用bsv库
let priKey = BSV.PrivateKey.fromRandom() //随机生成私钥
console.log(priKey.toHex()) //输出Hex格式私钥
console.log(priKey.toAddress()) //输出地址

保存后,在命令行里用如下node命令运行该代码

node .\random-key.js

随即输出一个私钥和对应的地址,例如

79f5876834b1e179de0112fd150e3170259fc2863328bb39a3f6f07403686158

1F9929pRu1TETjzd69Yf3znzG5baywqFva

记录好私钥,但千万不要公开。这个地址就可以用来收款。

可以在https://cli.im自行制作地址的二维码,方便手机钱包扫码付款。

 

转入少量BSV

为了测试我们的钱包,需要一定的币,你也可以在写完代码后再转币。

在此列举几个获取少量币的方法。

https://sv.cafe/buy 小额人民币快速买BSV,下限1元。

https://if.cash/bsv/faucet BSV水龙头,免费领取币,但可能失败。

https://www.freebsv.com BSV水龙头,未测试。

 

如果你想知道当前地址的余额,可以在区块链浏览器查询到,如

https://whatsonchain.com

https://satomoto.com/bitcoin-sv

https://www.oklink.com/bsv

 

编写转账功能

在工程文件夹里新建文件send-money.js,粘贴如下代码

const BSV = require('bsv') //引用bsv库
const MatterCloud = require('mattercloudjs') //引用MatterCloud库

const MatterCloudAPIKey = "CeJg9E1uuVJueBoJg6fkD5f5u7jBv4k7jj4cr6mmo8UTMzuqbq8Muzp3aXYTZ6bTh" //MatterCloud API Key
const matterAPI = MatterCloud.instance({
    api_key: MatterCloudAPIKey, 
})

let priKeyHex = "79f5876834b1e179de0112fd150e3170259fc2863328bb39a3f6f07403686158" //钱包私钥

let receiverAddresss = "1FjdJzaGXiUKQjnPBiTXqbuTPZMwypfoPC" //收款地址
let value = 1000 //收款金额(单位:Sat)

async function main() {

    let priKey = BSV.PrivateKey.fromHex(priKeyHex) //组装私钥
    let address = priKey.toAddress() //获取自己钱包的地址

    //获取锁定在钱包地址上的所有UTXO
    await matterAPI.getUtxos(address).then(async utxos => {

        let newTx = new BSV.Transaction() //创建一个transaction

        newTx.feePerKb(600) //设置手续费率为 0.6 Sat/Byte。 FIXME: 最终得到的tx的手续费和这里设置的不一致,原因不明
        //不同服务商的费率不同,经测试MatterCloud的广播API至少要 0.5 Sat/Byte。

        //将所有UTXO全部填入transaction的输入端(这是一种无脑做法,优秀的钱包应该智能地选择UTXO)
        let inputs = []
        utxos.forEach(utxo => {
            inputs.push(utxo)
        });
        newTx.from(inputs)

        //将收款地址对应的P2PKH输出添加到transaction的输出端
        let output = BSV.Transaction.Output({
            satoshis: value,
            script: BSV.Script.fromAddress(receiverAddresss)
        })
        newTx.addOutput(output)

        newTx.change(address) //将自己的地址设置为找零地址

        newTx.sign(priKey) //用私钥给transaction签署

        //生成16进制的transaction原数据,并输出,你可以用其他服务商来广播transaction
        let rawTx = newTx.toBuffer().toString('hex')
        console.log('RawTx:')
        console.log(rawTx)

        //用MatterCloud服务商广播transaction
        await matterAPI.sendRawTx(rawTx).then(res => {

            console.log('发送transaction成功:')
            console.log(res) //输出广播transaction的结果,包含txid

        }).catch(e => {
            console.error(e)
        })
    })
}

main()

 

如果你的钱包地址上已经有币,就可以转账了。

注意修改代码中的几个变量:

  • MatterCloudAPIKey。这是之前在MatterCloud免费获得的API Key。以后无需修改。
  • priKeyHex。这是你自己的钱包私钥,也就是刚刚生成的那个。以后很少修改。
  • receiverAddresss。本次转账的目标地址,每次转账时注意修改。
  • value。本次转账的金额,以Sat为单位,每次转账也应该修改。

 

用node命令运行脚本:

node .\send-money.js

如果发送成功,则输出如下

RawTx:
0100000002616f4ed2d6f9ad733e0e79fc12ea25e5022b99ce028edc7fdce7c3cbebf3a482010000008b483045022100faf05e98a313f9272af265e4685ad101ff670d0a34f82b1fe880d3275f32f948022046b3e6ed50de5ef5847f1d96a2b48fe9ae5aaa5d4667bb43724092acbed45e594141048da20227dc514bc19ba554caa81d373fe2714828fed99e6dec0ca05503da6e2ea1f631deb355502b77d3ce4cde5584e3810fd7d25777878d1b3a1dc6a89bd76bffffffff631540441b4dd04f7dc970b0059cdbd76a008186d675d050c1e737c254a53366010000008a473044022028dfe3e8243513847995cb97060b9eab0042fb718382ebc71bb52fb7055de77502204aaf50c30daefd46da76291bed5bf5288ac6fbc172afd8c0898e46419069159a4141048da20227dc514bc19ba554caa81d373fe2714828fed99e6dec0ca05503da6e2ea1f631deb355502b77d3ce4cde5584e3810fd7d25777878d1b3a1dc6a89bd76bffffffff02e8030000000000001976a914a1a18aa70fe9c31c041c23eb6ee57f18c7cda25888aceb250000000000001976a9149b1bc88717b3d068d55a12519f4fd7fcc31f5ab588ac00000000
发送transaction成功:
{ txid: '7467a9782d56230d3eefd857fbc3b57a6bf77a5e5034c2ce679ba334ae803d69' }

 

最后得到的txid,就是transaction的hash,可以用来在区块链浏览器上查到刚刚发送的transaction。

 

回顾

log里输出的rawTx是16进制表示的transaction原数据。可以用https://whatsonchain.com/decode解码tx。如果广播不成功,还可以用https://whatsonchain.com/broadcast直接广播transaction原数据。

 

本案例里用到了两个库。

其中,bsv库用来处理比特币的数据结构、底层协议相关的东西,如生成私钥、地址,组装和签署transaction。

MatterCloud是一个数据服务商,让我们可以通过远程API查询链上数据,或者广播transaction。我们可以把MatterCloud换成其他数据服务商(区块链浏览器也会提供数据服务),如

https://developers.whatsonchain.com

https://metasv.com/

 

附录

工程地址 https://github.com/fairwood/SimplestWallet