专业一点讲,Infura是一种IaaS(Infrastructure as a Service)产品,目的是为了降低访问以太坊数据的门槛。
通俗一点讲,Infura就是一个可以让你的dApp快速接入以太坊的平台,不需要本地运行以太坊节点。
从程序员的角度讲,Infura就是一个Web3 Provider,背后是负载均衡的API节点集群。使用它的好处就是,你永远不必担心连接的节点失效的问题,Infura会管理好这一切。
除此之外,Infura还可以很方便地接入IPFS,这是另外一个话题,这里就不讨论了。
使用infura的好处就是你不用花过多的时间去同步区块,可以直接使用
使用之前必须明白的是infura节点不掌控账户,所以想要发交易必须用自己的私钥签名,以此说明infura是安全的
最后,也是非常重要的一点:Infura目前是免费的。
二.如何使用Infura使用Infura首先需要注册一个账户,访问官网https://infura.io,点击注册并提供一个邮箱,会收到一封邮件,点击邮件中的链接激活就可以了,然后你就会看到下面的界面:
点击右上角的按钮,创建新项目,上面是我创建的ZERISION项目,点击VIEW PROJECT查看项目信息,就可以查到你专属的Project ID
接下来你就可以通过JSON RPC访问以太坊网络了,Infura支持主网和多个测试网,这里以MAINNET主网为例。比如我们想查询一下USDT(泰达币erc-20)合约中某个账户的余额,首先我们在blockchair上找到USDT合约的地址:
blockchair:https://blockchair.com/zh/ethereum/erc-20
erc20 智能合约各方法对应的签名编码
例如:transfer(address,uint256)
编码为:web3.sha3(“transfer(address,uint256)”).substring(0,10) -> “0xa9059cbb”
例如:balanceOf(address)
编码为:web3.sha3(“balanceOf(address)”).substring(0,10) -> “0x70a08231”
transfer(address,uint256): 0xa9059cbbbalanceOf(address):0x70a08231decimals():0x313ce567allowance(address,address): 0xdd62ed3esymbol():0x95d89b41totalSupply():0x18160dddname():0x06fdde03approve(address,uint256):0x095ea7b3transferFrom(address,address,uint256): 0x23b872dd我们需要查询余额,因此需要调用balanceOf()这个函数。我在blockchair上随便找了个地址0xE5E4f085c81342529b650c5f0E792980D673942B,然后把函数签名跟地址拼在一起生成交易数据。需要注意的是参数是64个字符,我们的地址只有40个字符,因此前面需要补24个0:
0x70a08231000000000000000000000000E5E4f085c81342529b650c5f0E792980D673942B接下来就可以用curl发起JSON RPC,查询该账户的余额了:(换成你自己的PROJECT ID)
# curl https://mainnet.infura.io/v3/<PROJECT ID> -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0xdaC17f958D2eE523A2206206994597c13D831ec7", "data":"0x70a08231000000000000000000000000E5E4f085c81342529b650c5f0E792980D673942B"}, "latest"],"id":1 }'curl https://mainnet.infura.io/v3/a965b25231ec4c8ba9c95f49c5f6f27e -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0xdaC17f958D2eE523A2206206994597c13D831ec7", "data":"0x70a08231000000000000000000000000E5E4f085c81342529b650c5f0E792980D673942B"}, "latest"],"id":1 }'返回结果:
{"jsonrpc":"2.0","id":1,"result":"0x0000000000000000000000000000000000000000000000000000000013e86f80"}可以看到这个大佬余额是13e86f80,转换成十进制334000000
接下来查询USDT ERC-20的decimals,只要把0x70a08231换成0x313ce567就可以了:
curl https://mainnet.infura.io/v3/a965b25231ec4c8ba9c95f49c5f6f27e -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0xdaC17f958D2eE523A2206206994597c13D831ec7", "data":"0x313ce567000000000000000000000000E5E4f085c81342529b650c5f0E792980D673942B"}, "latest"],"id":1 }'返回结果:
{"jsonrpc":"2.0","id":1,"result":"0x0000000000000000000000000000000000000000000000000000000000000006"}可以看到USDT的decimals是6,所以这个大佬这个地址上有334个USDT,也可以在浏览器上看看对不对
三.使用web3j连接infura第一步,先导入maven依赖
<dependency> <groupId>org.web3j</groupId> <artifactId>core</artifactId> <version>3.2.0</version></dependency>第二步,直接上代码
public static void main(String[] args) throws IOException {// 合约签名方法0x70a08231是查询余额的String DATA_PREFIX = "0x70a08231000000000000000000000000";// 合约签名方法0x313ce567是查询decimals的String DATA_DECIMAL_PREFIX = "0x313ce567000000000000000000000000";// USDT ERC-20的合约地址String CONTRACT_ADDRESS = "0xdaC17f958D2eE523A2206206994597c13D831ec7";// 查询地址String address = "0xE5E4f085c81342529b650c5f0E792980D673942B";// 获取余额String value = Admin.build(new HttpService("https://mainnet.infura.io")).ethCall(org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction(address,CONTRACT_ADDRESS, DATA_PREFIX + address.substring(2)), DefaultBlockParameterName.PENDING).send().getValue();// 16进制转10进制String valueStr = new BigInteger(value.substring(2), 16).toString();// 获取decimalsString decimals = Admin.build(new HttpService("https://mainnet.infura.io")).ethCall(org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction(address,CONTRACT_ADDRESS, DATA_DECIMAL_PREFIX + address.substring(2)), DefaultBlockParameterName.PENDING).send().getValue();String decimalStr = new BigInteger(decimals.substring(2), 16).toString();// 10的6次方BigDecimal WEI = new BigDecimal(Math.pow(10, Double.parseDouble(decimalStr)));BigDecimal balance = new BigDecimal(valueStr).divide(WEI, Integer.parseInt(decimalStr), RoundingMode.HALF_DOWN);System.out.println(balance);}执行结果: