zoukankan      html  css  js  c++  java
  • 区块链钱包开发

    一、安装钱包

    请参考另一篇随笔: 入口

    二、获取测试usdt(TestOmni)步骤:

    1、导入地址到钱包,往该地址充值测试比特币,
    2、然后往 moneyqMan7uh8FqdCA2BV5yZ8qVrc9ikLP 地址发送部分btc(testnet),即可返还部分usdt(TestOmni)
    3、omni_getbalance 方法查看到账情况 或者访问测试网络浏览器查询

    介绍一些常用的RPC接口命令

    查看地址私钥

    > ./bin/omnicore-cli -rpcconnect=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword dumpprivkey n1dnFGMxuxkDf1Ns5G2uYhaqk2ETWPuYQG(btc/usdt地址)
    

    查看到账:

    > ./bin/omnicore-cli -rpcconnect=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword getbalance
    

    获取交易信息:

    > ./bin/omnicore-cli -rpcconnect=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword omni_listtransactions 
    

    查看入账:

    > ./bin/omnicore-cli -rpcconnect=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword omni_getbalance mhf2ibPWMoeyibR2jS3jPLZQYTJsFSoG5r 1 (1: 表示彩色币id,usdt为31,钱包客户端我选择的是2) 
    

    测试网络进入QT桌面端

    > ./bin/omnicore-qt -testnet -server -rpcbind=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword 
    

    获取指定地址交易列表listUnspent

    > ./bin/omnicore-cli -rpcconnect=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword listunspent  0 999999 '["mhf2ibPWMoeyibR2jS3jPLZQYTJsFSoG5r"]'
    

    发送usdt

    > ./bin/omnicore-cli -rpcconnect=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword  omni_sendrawtx "mhf2ibPWMoeyibR2jS3jPLZQYTJsFSoG5r" "000000000000001f000000000000000a" "msis3b45PQriomes1zCAfNJpobggP1yusr" 
    

    导入特定地址到节点:

    > ./bin/omnicore-cli -rpcconnect=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword importprivkey cVKMjDVaWevxmRCrNXjTPpz77SSjWvQWp1eCj5zKBpEcaASK7Gib '' false  
    

    'cVKMjDVaWevxmRCrNXjTPpz77SSjWvQWp1eCj5zKBpEcaASK7Gib': 地址账户
    false:表示是否全节点扫描
    如果(btc/usdt)要通过api查询余额,rescan需要设置为true

    共享一个地址:
    usdt测试网络地址(有测试币):n1dnFGMxuxkDf1Ns5G2uYhaqk2ETWPuYQG
    私钥:cVZT8qHGs5g1qyVYmFgfUyz7CcRS7LX84xjgdNS8DdRbtJ5uXtYU

    三、开发

    这里主要介绍利用nodejs生成USDT地址,新建USDT转账交易等;

    1、环境安装

    (1)、8.x 以上版本nodejs、mongodb
    (2)、expresspm2

    2、依赖包 | btc官方提供的库和加密包等 | usdt基于btc底层协议,所以很多api可以共用

    (1)、randomstring
    (2)、bitcoinjs-lib
    (3)、bigi
    (4)、crypto

    3、部分模型准备

    (1) 地址表

        id: { type: String, required: true },
        address: { type: String, required: true, default: '' }, //USDT地址
        testnet: { type: Boolean, required: true, default: true }, //是否为测试网络地址
        privateKey: { type: String, required: true, default: '' }, //USDT地址私钥
        privateKeySalt: { type: String, required: true, default: '' }, //USDT地址加密盐
        hash: { type: String, required: true, default: '' }, //防篡改hash
        used: { type: Boolean, required: true, default: true }, //是否已被使用
        watch: { type: Boolean, required: true, default: false }, //是否已经添加到bitcoind监控列表
        invalid: { type: Boolean, required: true, default: false }, //是否已经失效
    

    (2) 交易表

        id: { type: String, required: true },
        txid: { type: String, required: true }, // 交易编号
        fee: { type: Number }, // 手续费
        sendingaddress: { type: String, required: true, default: '' }, // 发送方
        referenceaddress: { type: String, required: true, default: '' }, // 接收方
        ismine: { type: Boolean }, // 订单是否涉及钱包中的地址
        version: { type: Number }, // 版本
        type_int: { type: Number }, // 交易类型为数字
        type: { type: String, default: '' }, //  交易类型为字符串
        propertyid: { type: Number, required: true }, //要发送的令牌的标识符 如 31对应的是usdt
        divisible: { type: Boolean }, //令牌是否可以分割
        amount: { type: Number, required: true }, // 充值数量
        valid: { type: Boolean }, // 交易是否有效
        blockhash: { type: String }, // 相应块的hash
        blocktime: { type: Number }, // 最后处理的块的时间戳
        positioninblock: { type: Number }, //  块内交易的位置
        block: { type: Number }, // 当前块高度
        confirmations: { type: Number, default: 0 }, // 当前确认数
    

    3、部分代码块

    (1)、生成usdt钱包地址

      function createAddress(){
        try {
            let string = random.randomString(1048) //创建随机值
            let hash = bitcoin.crypto.sha256(string) //sha256加密,创建对应哈希
            let d = bigi.fromBuffer(hash) 
            let keyPair = new bitcoin.ECPair(d, null, { network: network }) //创建新私钥
            let privateKey = keyPair.toWIF()
            let publicAddress = keyPair.getAddress()
            let obj = {
                id: unique.uuid(),
                address: publicAddress,
                testnet: appConfig.usdt.testnet,
                privateKey: privateKey,
            }
            let addr = new Address(obj)
            addr.encryptPrivateKey() //私钥加密
            addr.createHash() //指定盐加密
            importAddrToNet(publicAddress).then(function(data) { // 添加到对应网络节点
                return addr.save() //保存地址到数据库
            }).then(function(d) {
                return res.json({
                    data: {
                        address: publicAddress //最后返回地址
                    }
                })
            }).catch(function(e) {
                ws.log('importAddrToNet error', e)
            })
        } catch (e) {
            ws.error(`catch importAddrToNet error ${e}`)
        }
    }
    

    (2)、生成交易

    usdt作为btc的一种彩色币,他的每次交易的原理,其实是生成btc交易,把usdt交易相关粘附在该笔交易上
    所以usdt转账需要提供少额的btc作为手续费, 一般是需要提供专门手续费地址账号。

     * @param {*} id  omni_id usdt:31
     * @param {*} sender_address 转出金额的临时地址
     * @param {*} sender_privatekey 转出临时地址的私钥
     * @param {*} value 转账金额
     * @param {*} receiver_address 接收地址
     * @param {*} fee 手续费
    const createTransaction = (sender_address, value, id) => {
        try {
            isBalanceEnough(sender_address, value, id).then(e => { //验证发送方余额
                if (e) {
                    return listUnspentForFee(sender_address, fee) //获取手续费地址账号的未花费交易unspentList
                } else {
                    ws.log('余额不足')
                    return reject(`余额不足,${e}`)
                }
            }).then(async (sender_tx) => {
                if (!tx.length) {
                    ws.log('等待上笔交易确认后再尝试..')
                    return resolve('等待上笔交易确认后再尝试..')
                }
                const _payload = await omniHelper.createpayloadSimplesend(id, parseFloat(value).toString()) //创建Usdt交易
                await omniHelper.createRawtransaction(sender_tx, {}) // 创建交易
                const opreturn = await omniHelper.createRawtx_opreturn(create, _payload) // //usdt交易附加到BTC交易上
                const reference = await omniHelper.createRawtx_reference(opreturn, receiver_address) //设置归总地址
                const data = await omniHelper.createRawtx_change(reference, sender_tx, sender_address, fee)  //填写手续费及找零地址
                const sign = await omniHelper.signRawtransaction(data, sender_tx, [sender_privatekey]) //获取原生交易hex
                const result = await omniHelper.sendRawtransaction(sign.hex) //广播交易
                return await isOnOmni(result) //验证结果
            }).then(data => {
                resolve(data)
            }).catch(e => {
                reject(e)
            })
        } catch (error) {
            ws.error(error)
        }
    }
    
    

    总结

    本篇随笔主要提供一种方案;

    退圈已久,需要探讨的可以留言或者私信,希望这些总结可以给到你们帮助;

    参考: 优化的js api库
  • 相关阅读:
    Jlist的用法
    Swing中Timer定时器的使用
    埃氏筛法
    ACM排序题
    《C语言程序设计》9.6
    从字符串中提取数
    字符串排序
    树—线索二叉树的创建&二叉树的后序遍历&中序线索化&中序遍历线索二叉树
    《大话数据结构》中介绍的三种树的存储结构的表示方法的总结
    day08
  • 原文地址:https://www.cnblogs.com/mapleChain/p/11527696.html
Copyright © 2011-2022 走看看