手把手教你区块链java开发智能合约nft(第四篇)-如何动态获取gasPrice和gasLimit?

2023-11-13

手把手教你区块链java开发智能合约nft(第三篇)-如何动态获取gasPrice和gasLimit?

初学区块链,那真叫一个痛苦并无助。如果没有人带你的话

今天写的这篇是在前面文章基础上写的,初学区块链的朋友建议先看我前面写的文章
手把手教你区块链java开发智能合约nft-第一篇
手把手教你区块链java开发智能合约nft-第二篇(部署第一个NFT智能合约)

什么是gas?什么是gasPrice?什么是gasLimit?

关于这几个概念,可以点击参考官方的说明

开发中怎么给入gasPrice和gasLimit?

对于这个问题,刚入门的我就非常吐槽了,在区块链上任何操作EVM的,都会耗用一定的gas,给少了矿工就罢工了,直接报错

刚入门的我真不了解这些,利用web3j 依赖进行java开发,在部署智能合约时,采用默认的方式获取gasPrice和gasLimit,demo如下

 		Web3j web3j = Web3j.build(new HttpService("http://192.168.159.101:9545/"));
        BigInteger chainId = web3j.ethChainId().send().getChainId();
        RawTransactionManager transactionManager = new RawTransactionManager(web3j, getCredentials(),chainId.longValue());
        NFT721 nft721 = NFT721.deploy(web3j,transactionManager,new DefaultGasProvider()),

然后就是使劲的报错,报错内容拿去网上搜索,还真搜索不到什么内容,简直就是一脸的懵逼,问了有一定经验的大佬,也不鸟我,最最无助的就是使劲的报错,却哪里也查不出问题

后面就超了官网上的某个地方,看到几个配置值,就随便配置了对应的值,竟然神奇的成功了

 NFT721 nft721 = NFT721.deploy(web3j,transactionManager,new StaticGasProvider(BigInteger.valueOf(22_000_000_000l),BigInteger.valueOf(6_700_000l)),

然后就一直用这个值进行开发测试,完事后向领导汇报情况,说当前这两个值配置死了,配置其他的都报错,后面领导说这个不能写死,要动态获取,于是,开始探索动态获取的方式

动态获取gasPrice

gasPrice动态获取还是比较简单的,因为可以直接调用web3j依赖的api,就能获取到

  private static BigInteger getGasPrice(Web3j web3j){
    BigInteger gasPrice=null;
    try {
      EthGasPrice send = web3j.ethGasPrice().send();
      gasPrice=send.getGasPrice();
    } catch (IOException e) {
      log.error("can't get gasPrice from private chain ,load default gasPrice:[{}],exception log:{}",gasPrice,e);
    }
    return gasPrice;
  }

这样就能获取到了动态gasPrice了,这个值是对应到节点上的gasPrice的值,如在geth attach上查看:

> eth.gasPrice
1000000000

动态获取gasLimit

获取gasLimit相对于gasPrice不同,不能直接获取到,需要计算即将要操作的方法,通过调用

      EthEstimateGas send = web3j.ethEstimateGas(transaction).send();
      gasLimit=send.getAmountUsed();

获取gasLimit值,难点主要是在transaction上

我在网上查阅了一番,发现资料少之又少,基本上没人给出怎么获取gasLimit预估值
于是就自己跟着前端发送的websocket去看,几乎所有的操作智能合约的,发送的数据获取gasLimit大概如下:

{
    "id": 141,
    "jsonrpc": "2.0",
    "method": "eth_estimateGas",
    "params": [
        {
            "data": "0x42966c68000000000000000000000000000000000000000000000000000000000000050a",
            "from": "0x2dd277910fca14b15e5e086dbac6732d6f397ef7",
            "to": "0x0b6a1b596a3d5817f3d34322a0ec013ca5439842"
        }
    ]
}

于是我就开始去研究transaction了,主要包含三个数据,from,to,data
from: 就是操作账户地址
to: 所要操作的智能合约的地址
data: 就是所要操作方法的参数加密串(加密串是我的理解,实际上是对方法进行加密)

那具体要怎么操作呢?

上代码:

  private static BigInteger getGasLimit(Web3j web3j,String from,String to,String data){
    BigInteger gasLimit=BigInteger.valueOf(GasConstant.GAS_LIMIT);;
    try {
      Transaction transaction = Transaction.createFunctionCallTransaction(from, null, null, null,to,data);
      EthEstimateGas send = web3j.ethEstimateGas(transaction).send();
      gasLimit=send.getAmountUsed();
      log.info("got gasLimit:[{}] from chain",gasLimit);
    } catch (IOException e) {
      log.error("can't get gasLimit from private chain,load default gasLimit:[{}],exception log :{}",gasLimit,e);
    }
    return gasLimit;
  }

这是封装了获取gasLimit的方法,根据传入参数就能获取到gasLimit

那怎么组装data?
我这里以智能合约Token 转账为例

    public static void transfer(String address,String recipient,String tokenAddress,String amount){
        Function transferFunction = Token.getTransferFunction(recipient, new BigInteger(amount));
        Token token = getToken(address, tokenAddress, FunctionEncoder.encode(transferFunction));

        try {
            token.transfer(transferFunction).sendAsync();
        } catch (Exception e) {
            log.error("transfer failure:",e);
            throw new BusinessException(40502,"transfer failure:"+e.getMessage());
        }
    }
      private static Token getToken(String address,String contractAddress,String data){
        Token load = Token.load(contractAddress, web3j, Web3Util.getTransactionManager(web3j,address), 		                    getContractGasProvider(web3j,address,contractAddress,data));
        return load;
    }
  public static ContractGasProvider getContractGasProvider(Web3j web3j,String from,String to,String data){
    BigInteger gasPrice = getGasPrice(web3j);
    BigInteger gasLimit = getGasLimit(web3j, from,to,data);
    log.info("ContractGasProvider gasPrice:{},gasLimit:{}",gasPrice,gasLimit);
    StaticGasProvider staticGasProvider = new StaticGasProvider(gasPrice,gasLimit );
    return staticGasProvider;
  }

其中,getTransferFunction方法和transfer 方法是我自己手动加入的方法,但实际上我是参考了Token转账的方法参数进行的组装
原转账方法如下:

    public RemoteFunctionCall<TransactionReceipt> transfer(String recipient, BigInteger amount) {
        final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(
                FUNC_TRANSFER, 
                Arrays.<Type>asList(new Address(recipient),
                new Uint256(amount)),
                Collections.<TypeReference<?>>emptyList());
        return executeRemoteCallTransaction(function);
    }

现在增加如下方法:

//这个是调用转账的方法
    public RemoteFunctionCall<TransactionReceipt> transfer(org.web3j.abi.datatypes.Function function ) {
        return executeRemoteCallTransaction(function);
    }

//获取即将调用操作的方法function,该方法会将参数和参数值组装为一个Function对象
    public static org.web3j.abi.datatypes.Function getTransferFunction(String recipient, BigInteger amount) {
        final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(
                FUNC_TRANSFER,
                Arrays.<Type>asList(new Address(recipient),
                        new Uint256(amount)),
                Collections.<TypeReference<?>>emptyList());
        return function;
    }

这样,就能预估出gasLimit的值,动态获取gasLimit了

如果操作的是其他的方法,自行修改对应的function方法和参数就可以了,当然,操作时也要记得改为自己对应的方法

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

手把手教你区块链java开发智能合约nft(第四篇)-如何动态获取gasPrice和gasLimit? 的相关文章

随机推荐

  • 【干货】今日头条的新闻推荐算法原理

    信息越来越海量 用户获取信息越来越茫然 而推荐算法则能有助于更好的匹配海量内容和用户需求 使之更加的 有的放矢 为让产业各方更好的了解算法分发的相关技术和原理 我们特整理了当下最具影响力的平台的相关干货 和各方分享 本期微信 我们将推荐影视
  • pip安装pytorch 清华镜像

    每次要搭配环境的时候就头大 资源基本是国外 下载起来特别慢 有些连服务器都访问不了 不用镜像 按照书上或者网上的正常流程搭配环境 基本上都是以超时告终 然后就在网上疯狂找资源 网上有人说是个程序员都会翻墙 我可能是个假的程序员吧 什么都不会
  • Arthas watch命令使用

    目录 属性遍历深度 1 watch 类全限定名 方法名 遍历深度为1的入参 对象 返回信息 2 watch 类全限定名 方法名 x n 观察遍历深度为n的入参 对象 返回信息 观察事件点 1 watch 类全限定名 方法名 params x
  • Python爬虫从入门到精通:(39)增量式爬虫_Python涛哥

    概念 检测网络数据更新的情况 以便于爬取到最新更新出来的数据 实现核心 去重 实战中去重的方式 记录表 记录表需要记录什么 记录的一定是爬取过的相关信息 例如某电影网 爬取过的相关信息 每一部电影详情页的url 只需要使用某一组数据 该组数
  • 一个产品的商业目标应该从哪些方面制定?

    产品面向社区治理相关服务 比如信息发布 事件调解 活动发布 数据统计等等 但感觉缺少合理的商业策略和商务模式 文心一言 一个产品的商业目标应该从以下几个方面制定 市场定位 确定你的产品的目标客户是谁 这可以是你的社区治理服务所面向的人群 也
  • 【数学公式】Mathpix和MathType等等

    MathML MathML指 数学标记语言 是XML语言的一个子集 用来在web网页 甚至部分软件中显示数学公式 简言之 就是使用特殊的类似HTML的标记在网页中显示数学公式 MathType公式编辑器 MathType是一个强大的数学公式
  • JSP的原理

    Tomcat的lib目录下的jasper jar包 这个包里面有一个HttpJspBase类 这个类我们看一下源码 Source code recreated from a class file by IntelliJ IDEA power
  • CC++ 标头和源文件:它们如何工作?

    本文将向您展示将程序划分为C中的组件部分或正确使用标头和源文件C 诀窍 介绍 我主要是为我的一个朋友写这篇文章的 但是 如果我不与大家分享这一点 我会对社区造成伤害 所以就在这里 我们将探索标头和源文件以及它们的作用 这些代码的大部分在 C
  • SSH框架简介篇

    文章目录 概述 目录结构 struts Spring Hibernate 总结 概述 SSH框架 Struts Spring Hibernate 是一种广泛应用的Java企业级开发框架组合 它将Struts Spring和Hibernate
  • LVM原理及配置

    1 简介 1 1 什么是LVM LVM是 Logical Volume Manager 逻辑卷管理 的简写 它由Heinz Mauelshagen在Linux 2 4内核上实现 目前最新版本为 稳定版1 0 5 开发版 1 1 0 rc2
  • 中国天气网接口

    中国天气weather com http m weather com cn data 101110101 html 六天预报 http www weather com cn data sk 101110101 html 实时天气信息 其中1
  • RSA pkcs1与pkcs8 java获取私钥

    RSA pkcs1与pkcs8 java获取私钥 目录 RSA pkcs1与pkcs8 java获取私钥 获取秘钥 获取pkcs1 格式秘钥 获取pkcs8格式秘钥 读取秘钥信息 解密 获取秘钥 maven依赖
  • 【网络】几种常见的协议

    几种常见的协议 DNS Domain Name System 域名解析协议 端口号 53 通过域名解析获得域名所对应的IP FTP File Transfer Protocol 文件传输协议 端口号 21 用户可通过客户机程序向远程主机上传
  • el-input正则限制

    el input限制只能输入1 9且只保留一位小数 return rules deductionPrice required true message 请输入折扣力度 trigger blur validator this valuePri
  • 栈溢出学习

    前言 跟着ctfwiki学习 所有题目都在ctfwiki上可以找到 加油加油 栈溢出原理 栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数 因而导致与其相邻的栈中的变量的值被改变 看一个简单的程序 include
  • 【枚举的定义;枚举变量的定义、初始化和赋值】(学习笔记16--枚举)

    目录 枚举的定义 枚举变量的定义 枚举变量的初始化与赋值 使用枚举类型 可以提高程序代码的健壮性和可读性 并且枚举成员属于常量 甚至可以使用枚举成员名作为维的大小 来进行数组的定义 枚举的定义 定义枚举的格式为 enum 枚举名 枚举成员1
  • Muduo网络库核心梳理

    Muduo网络库 Muduo网络库本身并不复杂 是一个新手入门C 面向对象网络编程的经典实战项目 但是 新手在刚刚上手读代码的时候 非常容易陷入代码的汪洋大海 迷失方向 本文旨在简要梳理Muduo网络库的核心内容 帮助初学者快速上手源码阅读
  • DES算法简单介绍及用法

    大家好 今天给大家分享一下DES加密 一 DES介绍 加密一般分为可逆加密和不可逆加密 其中可逆加密一般又分为对称加密和非对称加密 前者是我们使用公用密钥加密之后可以使用公用密钥再解密出来 而后者则是使用公用密钥加密之后必须使用私用密钥来解
  • MySQL这一章就够了(一)

    前言 呕心沥血5个月淦出本文 整理所有MySQL知识 我愿称之为地表最强MySQL MySql笔记 MySQL是关系型数据库 基于SQL查询的开源跨平台数据库管理系统 它最初是由瑞典MySQL AB公司开发的 现在它是Oracle Corp
  • 手把手教你区块链java开发智能合约nft(第四篇)-如何动态获取gasPrice和gasLimit?

    手把手教你区块链java开发智能合约nft 第三篇 如何动态获取gasPrice和gasLimit 初学区块链 那真叫一个痛苦并无助 如果没有人带你的话 今天写的这篇是在前面文章基础上写的 初学区块链的朋友建议先看我前面写的文章 手把手教你