Lightweight Ethereum Clients Using Web3j – 使用Web3j的轻量级Ethereum客户端

最后修改: 2018年 5月 10日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

This tutorial introduces Web3j, a Java implementation of the popular Web3 abstraction library.

本教程介绍了Web3j,一个流行的Web3抽象库的Java实现。

Web3j is used to interact with the Ethereum network by connecting to Ethereum nodes using JSON-RPC or familiar standards like HTTP, WebSockets, IPC.

Web3j用于与以太坊网络互动,通过使用JSON-RPC或熟悉的标准如HTTP、WebSockets、IPC连接到以太坊节点。

Ethereum is a whole topic unto itself so let’s first take a quick look at what it is!

以太坊本身就是一个完整的话题,所以让我们先快速了解一下它是什么

2. Ethereum

2.Ethereum

Ethereum is a (1) cryptocurrency (token symbol ETH), (2) distributed supercomputer, (3) blockchain, and (4) smart contract network written in Solidity.

以太坊是一个(1)加密货币(代币符号ETH),(2)分布式超级计算机,(3)区块链,以及(4)用Solidity.编写的智能合约网络。

In other words, Ethereum (the network) is run by a bunch of connected servers called nodes that communicate in a kind of mesh topology (technically, this is not exactly true but close enough to get a more solid understanding of how it all works).

换句话说,以太坊(网络)是由一群被称为节点的连接服务器运行的,它们以一种网状拓扑结构进行通信(从技术上讲,这并不完全正确,但足以让人更扎实地了解这一切的运作方式)。

Web3j, and its parent library called Web3, allows web applications to connect to one of those nodes and thereby submit Ethereum transactions, which are, for all intents and purposes, compiled Solidity smart contract functions that have been previously deployed to the Ethereum network. For more information on smart contracts see our article on creating and deploying them with Solidity here.

Web3j及其父库称为Web3允许Web应用程序连接到这些节点之一,从而提交Ethereum 交易,就所有的意图和目的而言,它们是经过编译的 Solidity 智能合约 功能,先前已经部署到Ethereum 网络。有关智能合约的更多信息,请参阅我们关于用 Solidity 创建和部署智能合约的文章这里

Each Node broadcasts its changes to every other node so that consensus and verification can be achieved. Thus, each node contains the entire history of the Ethereum blockchain simultaneously thereby creating a redundant backup of all the data, in a tamper-proof way, and via consensus and verification by all the other node in the network.\

每个节点将其变化广播给其他每个节点,以便达成共识和验证。因此,每个节点同时包含以太坊区块链的整个历史,从而以防篡改的方式,并通过网络中所有其他节点的共识和验证,创建一个所有数据的冗余备份。

For more detailed information on Ethereum, check out the official page.

有关以太坊的更多详细信息,请查看官方页面

3. Set Up

3.设置

To use the full suite of features provided by Web3j, we have to do a little bit more to get set up than usual. First, Web3j is supplied in several, free-standing, modules each of which can be optionally added to the core pom.xml dependency:

为了使用Web3j提供的全套功能,我们必须比平时多做一些设置。首先,Web3j是以几个独立的模块提供的,每个模块都可以选择性地添加到核心pom.xml依赖中。

<dependency>
    <groupId>org.web3j</groupId>
    <artifactId>core</artifactId>
    <version>3.3.1</version>
</dependency>

Please note that the team at Web3j provides a pre-built Spring Boot Starter with some configuration and limited functionality built right in!

请注意,Web3j的团队提供了一个预建的Spring Boot启动器,其中直接内置了一些配置和有限的功能!

We’ll restrict our focus to the core functionalities in this article (including how to add Web3j to a Spring MVC application, so compatibility with a wider-range of Spring webapps is obtained).

在这篇文章中,我们将把重点限制在核心功能上(包括如何将Web3j添加到Spring MVC应用中,从而获得与更多Spring webapp的兼容性)。

A full list of these modules can be found on Maven Central.

这些模块的完整列表可以在Maven Central上找到。

3.1. Compiling Contracts: Truffle or Solc

3.1.编译合同 Truffle或Solc

There are two primary ways to compile and deploy Ethereum smart contracts (.solc files):

有两种主要方式来编译和部署Ethereum智能合约(.solc文件)。

  1. The official Solidity compiler.
  2. Truffle (an abstraction suite for testing, deploying, and managing smart contracts).

We’ll stick with Truffle in this article. Truffle simplifies and abstracts the process of compiling smart contracts, migrating them, and deploying them to a network. It also wraps the Solc compiler letting us gain some experience with both.

Truffle简化和抽象了编译智能合约的过程,迁移它们,并将它们部署到网络中。它还封装了Solc编译器,让我们获得了一些关于这两者的经验。

To set up Truffle:

要设置Truffle。

$ npm install truffle -g
$ truffle version

Four key commands we’ll use to initialize our project respectively, compile our app, deploy our app to the Blockchain, and test it respectively:

我们将使用四个关键命令,分别用于初始化我们的项目,编译我们的应用程序,将我们的应用程序部署到区块链上,以及测试它。

$ truffle init
$ truffle compile
$ truffle migrate
$ truffle test

Now, let’s go over a simple example:

现在,我们来看看一个简单的例子。

pragma solidity ^0.4.17;

contract Example {
  function Example() {
    // constructor
  }
}

Which should yield the following ABI JSON when compiled:

编译后应产生以下ABI JSON。

{
  "contractName": "Example",
  "abi": [
    {
      "inputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "constructor"
    }
  ],
  "bytecode": "0x60606040523415600e57600080fd5b603580601b6...,
  "deployedBytecode": "0x6060604052600080fd00a165627a7a72305...,
  //...
}

We can then use the supplied bytecode and ABI within our application to interact with the deployed contracts!

然后,我们可以在我们的应用程序中使用所提供的字节码和ABI,与已部署的合同进行交互。

3.2. Testing Contracts: Ganache

3.2.测试合同 Ganache

One of the easiest ways to work with an Ethereum testnet is to launch own Ganache server. We’ll use the pre-built, out-of-the-box, solution since it’s the easiest to set up and configure. It also provides an interface and server shell for Ganache CLI which drives Ganache under-the-hood.

使用以太坊测试网的最简单方法之一是启动自己的Ganache服务器。我们将使用预先构建的、开箱即用的解决方案,因为它是最容易设置和配置的。它还为Ganache CLI提供了一个接口和服务器外壳,它在后台驱动Ganache。

We can connect to our Ganache server on the default supplied URL address: http://localhost:8545 or http://localhost:7545.

我们可以通过默认提供的URL地址连接到我们的Ganache服务器。http://localhost:8545 或 http://localhost:7545。

There are a couple of other popular approaches to setting up a test network including using Meta-Mask, Infura, or Go-Lang and Geth.

还有一些其他流行的方法来设置测试网络,包括使用Meta-MaskInfura,或者Go-Lang和Geth

We’ll stick with Ganache in this article since setting up your own GoLang instance (and configuring it as a custom testnet) can be pretty tricky and since the status of Meta-Mask on Chrome is presently uncertain.

在本文中,我们将坚持使用Ganache,因为建立自己的GoLang实例(并将其配置为自定义测试网)可能相当棘手,而且目前Chrome上的Meta-Mask的状态还不确定。

We can use Ganache for manual testing scenarios (when debugging or completing our integration testing) or use them for automated testing scenarios (which we have to build our tests around since, in such circumstances, we might not have the available endpoints).

我们可以将Ganache用于手动测试场景(在调试或完成我们的集成测试时),或者将它们用于自动测试场景(我们必须围绕这些场景建立我们的测试,因为在这种情况下,我们可能没有可用的端点)。

4. Web3 and RPC

4.Web3和RPC

Web3 provides a facade and interface for interacting easily with the Ethereum blockchain and Ethereum server nodes. In other words, Web3 facilitates intercommunication between clients and the Ethereum Blockchain by way of JSON-RPC. Web3J is the official Java port of Web3.

Web3提供了一个门面和接口,以方便与以太坊区块链和以太坊服务器节点进行互动。换句话说,Web3通过JSON-RPC的方式促进了客户和以太坊区块链之间的互通Web3J是Web3的官方Java端口

We can initialize Web3j for use within our application by passing in a provider (e.g. – the endpoint of a third-party or local Ethereum node):

我们可以通过传入一个提供者(例如–第三方或本地Ethereum节点的端点)来初始化Web3j,以便在我们的应用程序中使用。

Web3j web3a = Web3j.build(new HttpService());
Web3j web3b = Web3j.build(new HttpService("YOUR_PROVIDER_HERE"));
Web3j myEtherWallet = Web3j.build(
  new HttpService("https://api.myetherapi.com/eth"));

The third option shows how to add in a third-party provider (thereby connecting with their Ethereum node). But we also have the option to leave our provider option empty. In that case, the default port will be used (8545) on localhost instead.

第三个选项显示了如何加入第三方提供者(从而与他们的以太坊节点连接)。但我们也可以选择让我们的提供者选项为空。在这种情况下,将使用localhost上的默认端口(8545),而不是

5. Essential Web3 Methods

5.基本的Web3方法

Now that we know how to initialize our app to communicate with the Ethereum blockchain, let’s look at a few, core, ways to interact with the Ethereum blockchain.

现在我们知道了如何初始化我们的应用程序以与以太坊区块链进行通信,让我们看看与以太坊区块链互动的一些核心方式。

It’s a good policy to wrap your Web3 methods with a CompleteableFuture to handle the asynchronous nature of JSON-RPC requests made to your configured Ethereum node.

CompleteableFuture包装你的Web3方法,以处理向你配置的Ethereum节点发出的JSON-RPC请求的异步性质,这是一个很好的政策。

5.1. Current Block Number

5.1.当前区块编号

We can, for example, return the current block number:

例如,我们可以返回当前区块编号

public EthBlockNumber getBlockNumber() {
    EthBlockNumber result = new EthBlockNumber();
    result = this.web3j.ethBlockNumber()
      .sendAsync()
      .get();
    return result;
}

5.2. Account

5.2.帐户

To get the account of a specified address:

要获得指定地址的账户

public EthAccounts getEthAccounts() {
    EthAccounts result = new EthAccounts();
    result = this.web3j.ethAccounts()
        .sendAsync() 
        .get();
    return result;
}

5.3. Number of Account Transactions

5.3.账户事务的数量

To get the number of transactions of a given address:

要获得一个给定地址的交易数量

public EthGetTransactionCount getTransactionCount() {
    EthGetTransactionCount result = new EthGetTransactionCount();
    result = this.web3j.ethGetTransactionCount(DEFAULT_ADDRESS, 
      DefaultBlockParameter.valueOf("latest"))
        .sendAsync() 
        .get();
    return result;
}

5.4. Account Balance

5.4.账户余额

And finally, to get the current balance of an address or wallet:

最后,为了获得一个地址或钱包的当前余额:

public EthGetBalance getEthBalance() {
    EthGetBalance result = new EthGetBalance();
    this.web3j.ethGetBalance(DEFAULT_ADDRESS, 
      DefaultBlockParameter.valueOf("latest"))
        .sendAsync() 
        .get();
    return result;
}

6. Working With Contracts in Web3j

6.在Web3j中使用合同

Once we’ve compiled our Solidity contract using Truffle, we can work with our compiled Application Binary Interfaces (ABI) using the standalone Web3j command line tool available here or as a free-standing zip here.

一旦我们使用 Truffle 编译了我们的 Solidity 合约,我们就可以使用独立的 Web3j 命令行工具这里或作为独立的 zip这里来处理我们编译的应用程序二进制接口ABI)。

6.1. CLI Magic

6.1.CLI魔法

We can then automatically generate our Java Smart Contract Wrappers (essentially a POJO exposing the smart contract ABI) using the following command:

然后,我们可以使用以下命令自动生成我们的Java智能合约封装器(本质上是一个暴露智能合约ABI的POJO)。

$ web3j truffle generate [--javaTypes|--solidityTypes] 
  /path/to/<truffle-smart-contract-output>.json 
  -o /path/to/src/main/java -p com.your.organisation.name

Running the following command in the root of the project:

在项目的根部运行以下命令。

web3j truffle generate dev_truffle/build/contracts/Example.json 
  -o src/main/java/com/baeldung/web3/contract -p com.baeldung

generated our Example class:

生成了我们的Example类。

public class Example extends Contract {
    private static final String BINARY = "0x60606040523415600e576...";
    //...
}

6.2. Java POJO’s

6.2. Java的POJO

Now that we have our Smart Contract Wrapper, we can create a wallet programmatically and then deploy our contract to that address:

现在我们有了智能合约封装器,我们可以以编程方式创建一个钱包,然后将我们的合约部署到该地址

WalletUtils.generateNewWalletFile("PASSWORD", new File("/path/to/destination"), true);
Credentials credentials = WalletUtils.loadCredentials("PASSWORD", "/path/to/walletfile");

6.3. Deploy a Contract

6.3.部署一个合同

We can deploy our contract like so:

我们可以像这样部署我们的合同。

Example contract = Example.deploy(this.web3j,
  credentials,
  ManagedTransaction.GAS_PRICE,
  Contract.GAS_LIMIT).send();

And then get the address:

然后得到地址。

contractAddress = contract.getContractAddress();

6.4. Sending Transactions

6.4.发送事务

To send a Transaction using the Functions of our Contract we  can initialize a Web3j Function with a List of input values and a List of output parameters:

为了使用我们的ContractFunctions发送Transaction,我们可以用输入值的List和输出参数的List初始化一个Web3jFunction

List inputParams = new ArrayList();
List outputParams = new ArrayList();
Function function = new Function("fuctionName", inputParams, outputParams);
String encodedFunction = FunctionEncoder.encode(function);

We can then initialize our Transaction with necessary gas (used to execute of the Transaction) and nonce parameters:

然后我们可以用必要的gas(用于执行Transaction)和nonce参数初始化我们的Transaction

BigInteger nonce = BigInteger.valueOf(100);
BigInteger gasprice = BigInteger.valueOf(100);
BigInteger gaslimit = BigInteger.valueOf(100);

Transaction transaction = Transaction
  .createFunctionCallTransaction("FROM_ADDRESS", 
    nonce, gasprice, gaslimit, "TO_ADDRESS", encodedFunction);

EthSendTransaction transactionResponse = web3j.ethSendTransaction(transaction).sendAsync().get();
transactionHash = transactionResponse.getTransactionHash();

For a full list of smart contract functionalities see the official docs.

有关智能合约功能的完整列表,请参见官方文档

7. Conclusion

7.结论

That’s it! We’ve set up a Java Spring MVC app with Web3j – it’s Blockchain time!

这就是了!我们已经用Web3j建立了一个Java Spring MVC应用–区块链时间到了!。

As always, the code examples used in this article are available over on GitHub.

一如既往,本文中使用的代码示例可在GitHub上获得。