V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jimi2018
V2EX  ›  Java

Java 类库 web3j 开发以太坊智能合约快速入门

  •  2
     
  •   jimi2018 · 2018-06-18 10:37:25 +08:00 · 4140 次点击
    这是一个创建于 2352 天前的主题,其中的信息可能已经有所发展或是发生改变。

    web3j 简介

    web3j 是一个轻量级、高度模块化、响应式、类型安全的 Java 和 Android 类库提供丰富 API,用于处理以太坊智能合约及与以太坊网络上的客户端(节点)进行集成。

    可以通过它进行以太坊区块链的开发,而无需为你的 java 应用平台编写集成代码。

    快速启动

    想要快速启动的话,有一个Web3j demo 示例项目可用,演示了通过 Web3j 开发以太坊的许多核心特征,其中包括:

    • 连接到以太网网络上的节点
    • 加载一个以太坊钱包文件
    • 将以太币从一个地址发送到另一个地址
    • 向网络部署智能合约
    • 从部署的智能合约中读取值
    • 更新部署的智能合约中的值
    • 查看由智能合约记录的事件

    web3j 入门

    首先将最新版本的 web3j 安装到项目中。

    Maven

    Java 8:

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

    Android:

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

    Gradle

    Java 8:

    compile ('org.web3j:core:3.4.0')
    

    Android:

    compile ('org.web3j:core:3.3.1-android')
    

    启动客户端

    需要启动一个以太坊客户端,当然如果你已经启动了就不需要再次启动。

    如果是geth的话这么启动:

    $ geth --rpcapi personal,db,eth,net,web3 --rpc --rinkeby
    

    如果是Parity启动:

    $ parity --chain testnet
    

    如果使用Infura客户端提供的免费的云端服务,这么启动:

    Web3j web3 = Web3j.build(new HttpService("https://morden.infura.io/your-token"));
    

    如果想进一步的了解 infura,请参阅Using Infura with web3j

    在网络上如何获得以太币的相关文档可以看这个:testnet section of the docs

    当不需要 Web3j 实例时,需要调用shutdown方法来释放它所使用的资源。

    web3.shutdown()
    

    发送请求

    发送同步请求

    Web3j web3 = Web3j.build(new HttpService());  // defaults to http://localhost:8545/
    Web3ClientVersion web3ClientVersion = web3.web3ClientVersion().send();
    String clientVersion = web3ClientVersion.getWeb3ClientVersion();
    

    ** 使用 CompletableFuture (Future on Android) 发送异步请求**

    Web3j web3 = Web3j.build(new HttpService());  // defaults to http://localhost:8545/
    Web3ClientVersion web3ClientVersion = web3.web3ClientVersion().sendAsync().get();
    String clientVersion = web3ClientVersion.getWeb3ClientVersion();
    

    *使用 RxJava 的 Observable

    Web3j web3 = Web3j.build(new HttpService());  // defaults to http://localhost:8545/
    web3.web3ClientVersion().observable().subscribe(x -> {
        String clientVersion = x.getWeb3ClientVersion();
        ...
    });
    

    注意 Android 使用方式

    Web3j web3 = Web3jFactory.build(new HttpService());  // defaults to http://localhost:8545/
    ...
    

    IPC

    Web3j 还支持通过文件套接字快速运行进程间通信( IPC ),支持客户端在相同的主机上同时运行 Web3j。在创建服务时,使用相关的IPCService就可以实现而不需要通过HTTPService

    // OS X/Linux/Unix:
    Web3j web3 = Web3j.build(new UnixIpcService("/path/to/socketfile"));
    ...
    
    // Windows
    Web3j web3 = Web3j.build(new WindowsIpcService("/path/to/namedpipefile"));
    ...
    

    需要注意:IPC 通信在 web3j-android 中不可用。

    通过 java 打包以太坊智能合约

    Web3j 可以自动打包智能合同代码,以便在不脱离 JVM 的情况下进行以太坊智能合同部署和交互。

    要打包代码,需要先编译智能合同:

    $ solc <contract>.sol --bin --abi --optimize -o <output-dir>/
    

    然后用web3j 的命令行工具打包代码:

    web3j solidity generate /path/to/<smart-contract>.bin /path/to/<smart-contract>.abi -o /path/to/src/main/java -p com.your.organisation.name
    

    接下来就可以新建和部署智能合约了:

    Web3j web3 = Web3j.build(new HttpService());  // defaults to http://localhost:8545/
    Credentials credentials = WalletUtils.loadCredentials("password", "/path/to/walletfile");
    
    YourSmartContract contract = YourSmartContract.deploy(
            <web3j>, <credentials>,
            GAS_PRICE, GAS_LIMIT,
            <param1>, ..., <paramN>).send();  // constructor params
    

    或者使用一个现有的智能合约:

    YourSmartContract contract = YourSmartContract.load(
            "0x<address>|<ensName>", <web3j>, <credentials>, GAS_PRICE, GAS_LIMIT);
    

    然后就可以进行智能合约的交互了:

    TransactionReceipt transactionReceipt = contract.someMethod(
                 <param1>,
                 ...).send();
    

    调用智能合约:

    Type result = contract.someMethod(<param1>, ...).send();
    

    更多关于打包的资料可以看这里:Solidity smart contract wrappers

    Filters

    web3j 的响应式函数可以使观察者通过事件去通知消息订阅者变得很简单,并能够记录在区块链中。接收所有新的区块并把它们添加到区块链中:

    Subscription subscription = web3j.blockObservable(false).subscribe(block -> {
        ...
    });
    

    接收所有新的交易并把它们添加到区块链中:

    Subscription subscription = web3j.transactionObservable().subscribe(tx -> {
        ...
    });
    

    接收所有已经提交到网络中等待处理的交易。(他们被统一的分配到一个区块之前。)

    Subscription subscription = web3j.pendingTransactionObservable().subscribe(tx -> {
        ...
    });
    

    或者你重置所有的区块到最新的位置,那么当有新建区块的时候会通知你。

    Subscription subscription = catchUpToLatestAndSubscribeToNewBlocksObservable(
            <startBlockNumber>, <fullTxObjects>)
            .subscribe(block -> {
                ...
    });
    

    主题过滤也被支持:

    EthFilter filter = new EthFilter(DefaultBlockParameterName.EARLIEST,
            DefaultBlockParameterName.LATEST, <contract-address>)
                 .addSingleTopic(...)|.addOptionalTopics(..., ...)|...;
    web3j.ethLogObservable(filter).subscribe(log -> {
        ...
    });
    

    当不再需要时,订阅也应该被取消:

    subscription.unsubscribe();
    

    **注意:Infura 中不支持 filters。 **

    需要了解更多有关过滤器和事件的信息可以查看Filters and EventsWeb3jRx的接口。

    交易

    Web3j 支持使用以太坊钱包文件(推荐的)和用于发送事务的以太坊客户端管理命令。

    使用以太钱包文件发送以太币给其他人:

    Web3j web3 = Web3j.build(new HttpService());  // defaults to http://localhost:8545/
    Credentials credentials = WalletUtils.loadCredentials("password", "/path/to/walletfile");
    TransactionReceipt transactionReceipt = Transfer.sendFunds(
            web3, credentials, "0x<address>|<ensName>",
            BigDecimal.valueOf(1.0), Convert.Unit.ETHER)
            .send();
    

    或者你希望建立你自己定制的交易:

    Web3j web3 = Web3j.build(new HttpService());  // defaults to http://localhost:8545/
    Credentials credentials = WalletUtils.loadCredentials("password", "/path/to/walletfile");
    
    // get the next available nonce
    EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(
                 address, DefaultBlockParameterName.LATEST).send();
    BigInteger nonce = ethGetTransactionCount.getTransactionCount();
    
    // create our transaction
    RawTransaction rawTransaction  = RawTransaction.createEtherTransaction(
                 nonce, <gas price>, <gas limit>, <toAddress>, <value>);
    
    // sign & send our transaction
    byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
    String hexValue = Numeric.toHexString(signedMessage);
    EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).send();
    // ...
    

    使用 Web3j 的Transfer进行以太币交易要简单得多。

    使用以太坊客户端的管理命令(如果你的钱包密钥已经在客户端存储):

    Admin web3j = Admin.build(new HttpService());  // defaults to http://localhost:8545/
    PersonalUnlockAccount personalUnlockAccount = web3j.personalUnlockAccount("0x000...", "a password").sendAsync().get();
    if (personalUnlockAccount.accountUnlocked()) {
        // send a transaction
    }
    

    如果你想使用 Parity ’ s Personal 或者 Trace 功能, 或者 Geth ’ s Personal 客户端 APIs,可以使用org.web3j:parityorg.web3j:geth模块。

    命令行工具

    web3j 的 jar 包为每一个版本都提供命令行工具。命令行工具允许你直接通过一些命令使用 web3j 的一些功能:

    • 钱包创建
    • 钱包密码管理
    • 资金从钱包转移到另一个
    • solidity 编写的智能合同功能打包

    请参阅文档以获得命令行相关的进一步的信息。

    其他的细节

    java8 bulid:

    • Web3j 提供对所有响应类型的安全访问。可选的或 null 响应 java 8 都支持。
    • 异步请求包在一个 java 8 的CompletableFutures。Web3j 提供了围绕所有异步请求的打包工具,以确保在执行期间可以捕获任何异常,而不只是丢弃。由于在完全检查中会有很多缺少支持的异常情况,这些异常通常被确定为未检测到的异常,导致检测过程出现问题。有关详细信息,请参见 Async.run()及其关联 test

    在 java 8 的 Android 版本:

    • 包数量作为 BigIntegers返回。对于简单的结果,可以通过Response.getResult()获取字符串类型的数量结果。
    • 还可以通过在 HttpService 和 IpcService 类中存在的includeRawResponse参数将原生的 JSON 包放置在响应中。

    原文请访问:web3js开发以太坊智能合约快速入门

    1 条回复    2018-07-12 15:11:42 +08:00
    geek123
        1
    geek123  
       2018-07-12 15:11:42 +08:00
    不错。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1175 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 18:36 · PVG 02:36 · LAX 10:36 · JFK 13:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.