美文网首页
以太坊开发(三十)Bug修复:使用Web3.js转账带小数数量的

以太坊开发(三十)Bug修复:使用Web3.js转账带小数数量的

作者: yuyangray | 来源:发表于2018-12-31 18:38 被阅读82次

    致歉

    首先和大家说句抱歉!最近项目太忙,有很多朋友私信我,要我帮忙解决下问题。很多问题我也需要去试一下才能知道问题出在哪里,但是确实忙的连这个时间也没有。再次抱歉!

    前言

    之前写的文章以太坊开发(二十九)[升级版]使用Web3.js+Node.js封装成接口以供钱包管理/查询/转账,提供了使用Web3.js转账的方法。之前没有测试转账带小数的代币,例如9999.9999。现在项目测试时发现会报错,错误信息大致是web3.utils.toHex(amount)参数不支持小数,也就是在转账的这一步出错:

    let tokenTransferData = await contract.methods.transfer(receiverAddress, 
            web3.utils.toHex(amount)).encodeABI()
    
    

    按理说前面已经获取了代币小数位,然后将传入的要转账的代币数量乘以了10的小数位的次方,本来应该不会再出现小数位:

    let decimals = await contract.methods.decimals().call()
    let amount = num * Math.pow(10, decimals)
    

    假如此代币的小数位为4,转账数量为9999.9999那么此处amount应该是:

    9999.9999 * Math.pow(10, 4)
    =
    9999.9999 * 10000
    =
    99999999
    

    但通过观察输出,实际结果为99999999.0001,存在小数位,所以在后面web3.utils.toHex(99999999.0001)时报错。

    解决

    原因和解决方法可以查看下面这篇文章:Nodejs学习笔记(十七)--- 浮点运算decimal.js

    需要引入decimal.js进行处理。安装过程不再赘述,直接看修改后的代码:

    Token转账代码修改:

    旧:

     let decimals = await contract.methods.decimals().call()
     let amount = num * Math.pow(10, decimals)
    

    新:

    let decimals = await contract.methods.decimals().call()
    let amount = new decimal(num).mul(new decimal(Math.pow(10, decimals))).toNumber()
    

    Token余额查询也需要修改:

    旧:

    try {
            let balance = await contract.methods.balanceOf(address).call()
            ctx.body = await Promise.resolve({
                code: 0,
                data: balance / Math.pow(10, decimals),
                message: 'Success',
            })
        } catch (error) {
            ctx.body = await Promise.resolve({
                code: 1,
                data: {},
                message: error.stack,
            })
        }
    

    新:

    try {
            let balance = await contract.methods.balanceOf(address).call()
            ctx.body = await Promise.resolve({
                code: 0,
                data: new decimal(balance).div(new decimal(Math.pow(10, decimals))).toNumber(),
                message: 'Success',
            })
        } catch (error) {
            ctx.body = await Promise.resolve({
                code: 1,
                data: {},
                message: error.stack,
            })
        }
    

    相关文章

      网友评论

          本文标题:以太坊开发(三十)Bug修复:使用Web3.js转账带小数数量的

          本文链接:https://www.haomeiwen.com/subject/xjjwlqtx.html