How to integrate Web3j to java project

本文介绍了如何在Java项目中整合Web3j库,包括安装solc和web3j-cli,编译 Solidity 合约,生成Java包装器,配置Maven依赖,并创建Java类来加载和操作智能合约。还提供了一个单元测试示例,展示了通过socks5代理连接到BSC-TEST RPC点进行区块链操作。

1. Environment prepare

1.1. Install solc

npm install -g solc

Check if success use this command:

solcjs --version

success like this:

在这里插入图片描述

1.2. Install web3j-cli

Download web3j-cli 1.4.1 from https://github.com/web3j/web3j-cli/releases
for example I used v1.4.1 :

在这里插入图片描述
extract zip files to local file system:

在这里插入图片描述
set web3j-cli’s /bin folder to system environment path:

在这里插入图片描述
install finish, check version:

在这里插入图片描述

1.3. Contract

Here I use the contract “StandardToken.sol” for testing. It can be download at github ( E.G. https://github.com/tintinweb/smart-contract-sanctuary)

在这里插入图片描述

2. Compile

Use command solcjs to compile *.sol file to get .abi and .bin files like below:

solcjs StandardToken.sol --bin --abi --optimize -o .\

I got files like this:

在这里插入图片描述

3. Generate contract JAVA Wrapper

Command usage:

web3j solidity generate -a \<abiFile\> -b \<binFile\> -o \<destinationFileDir\> -p \<packageName\>

E.G.

在这里插入图片描述
在这里插入图片描述

4. Integration

4.1. Maven dependencies:

Add dependencies to pom.xml like :

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.web3j</groupId>
            <artifactId>core</artifactId>
            <version>5.0.0</version>
        </dependency>
    </dependencies>

4.2. Create java classes:

Copy contract wrapper file to java project and rename it to “StandardTokenContract.java” like below:

在这里插入图片描述

Here’s a helper class written by java named “ContractLoader” :


import okhttp3.OkHttpClient;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.response.EthGasPrice;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.Contract;
import org.web3j.tx.gas.ContractGasProvider;
import org.web3j.tx.gas.StaticGasProvider;
import org.web3j.utils.Convert;

import java.lang.reflect.Method;
import java.math.BigInteger;
import java.net.InetSocketAddress;
import java.net.Proxy;

public final class ContractLoader {
    private static String proxyHost;
    private static int proxyPort;
    private static String rpcUrl;

    private ContractLoader() {

    }

    public static void env(String proxyHost,
                           int proxyPort,
                           String rpcUrl) {
        ContractLoader.proxyHost = proxyHost;
        ContractLoader.proxyPort = proxyPort;
        ContractLoader.rpcUrl = rpcUrl;
    }

    /**
     * Load contract only read block data with default gas-limit 3000000.
     *
     * @param contractAddress contract which want to operate
     * @param contractClazz   java class of contract build by web3j-cli-shadow-{version}. E.G.web3j generate solidity -a=.\StandardToken_sol_StandardToken.abi -b=.\StandardToken_sol_StandardToken.bin -o=.\ -p=cn.netoday.web3j-test
     * @param <T>             return type witch contract java class build by web3j-cli-shadow extends org.web3j.tx.Contract
     * @return implements of org.web3j.tx.Contract
     * @throws Exception Exception
     */
    public static <T extends Contract> T getContract(String contractAddress,
                                                     Class<T> contractClazz) throws Exception {
        return getContract("0000000000000000000000000000000000000000000000000000000000000000",
                Convert.toWei("3000000", Convert.Unit.WEI).toBigInteger(),
                contractAddress,
                contractClazz);
    }

    /**
     * Load contract with read and write block data with default gas-limit 3000000.
     *
     * @param senderPrivateKey msg.sender‘s private key. It can operate msg.sender's private assets if provided.
     * @param contractAddress  contract which want to operate
     * @param contractClazz    java class of contract build by web3j-cli-shadow-{version}. E.G.web3j generate solidity -a=.\StandardToken_sol_StandardToken.abi -b=.\StandardToken_sol_StandardToken.bin -o=.\ -p=cn.netoday.web3j-test
     * @param <T>              return type witch contract java class build by web3j-cli-shadow extends org.web3j.tx.Contract
     * @return implements of org.web3j.tx.Contract
     * @throws Exception Exception
     */
    public static <T extends Contract> T getContract(String senderPrivateKey,
                                                     String contractAddress,
                                                     Class<T> contractClazz) throws Exception {
        return getContract(senderPrivateKey,
                Convert.toWei("3000000", Convert.Unit.WEI).toBigInteger(),
                contractAddress,
                contractClazz);
    }

    /**
     * Load contract with read and write block data with customize gas-limit.
     *
     * @param senderPrivateKey msg.sender‘s private key. It can operate msg.sender's private assets if provided.
     * @param gasLimit         call contract with customize gas-limit
     * @param contractAddress  contract which want to operate
     * @param contractClazz    java class of contract build by web3j-cli-shadow-{version}. E.G.web3j generate solidity -a=.\StandardToken_sol_StandardToken.abi -b=.\StandardToken_sol_StandardToken.bin -o=.\ -p=cn.netoday.web3j-test
     * @param <T>              return type witch contract java class build by web3j-cli-shadow extends org.web3j.tx.Contract
     * @return implements of org.web3j.tx.Contract
     * @throws Exception Exception
     */
    public static <T extends Contract> T getContract(String senderPrivateKey,
                                                     BigInteger gasLimit,
                                                     String contractAddress,
                                                     Class<T> contractClazz) throws Exception {
        if (null == ContractLoader.rpcUrl || "".equals(ContractLoader.rpcUrl)) {
            throw new Exception("Rpc url can not be empty!");
        }

        //set proxy
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if (null != ContractLoader.proxyHost && !"".equals(ContractLoader.proxyHost) && ContractLoader.proxyPort > 0) {
            builder.proxy(new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(ContractLoader.proxyHost, ContractLoader.proxyPort)));
        }
        OkHttpClient client = builder.build();

        //initial operation for web3j
        Web3j web3 = Web3j.build(new HttpService(ContractLoader.rpcUrl, client));
        Credentials credentials = Credentials.create(senderPrivateKey);
        EthGasPrice gasPrice = web3.ethGasPrice().sendAsync().get();

        //reflection of contract
        T result = null;
        if (gasPrice != null) {
            Method method = contractClazz.getMethod("load", String.class, Web3j.class, Credentials.class, ContractGasProvider.class);
            result = (T) method.invoke(contractClazz,
                    contractAddress,
                    web3,
                    credentials,
                    new StaticGasProvider(gasPrice.getGasPrice(), gasLimit)
            );
        }
        return result;
    }
}

And here’s a java unit test which used the BSC-TEST rpc point via socks5 proxy:


import com.yayd.contracthelper.ContractLoader;
import com.yayd.contracthelper.StandardTokenContract;
import org.junit.Test;
import org.web3j.utils.Convert;

/**
 * Unit test for simple App.
 */
public class AppTest {
    private static final String PRIVATE_KEY = "here is your wallet private key to authority";
    private static final String RPC_URL = "https://data-seed-prebsc-1-s3.binance.org:8545/";
    private static final String CONTRACT_ADDRESS = "here is your contract address on blockchain";
    public static final String PROXY_HOSTNAME = "127.0.0.1";
    public static final int PROXY_PORT = 10808;

    /**
     * Test call blockchain
     */
    @Test
    public void testTransfer() {
        try {
            ContractLoader.env(
                    PROXY_HOSTNAME,
                    PROXY_PORT,
                    RPC_URL
            );
            //Load contract only read block data with default gas-limit 3000000.
            StandardTokenContract contract = ContractLoader.getContract(
                    CONTRACT_ADDRESS,
                    StandardTokenContract.class);
            System.out.println(contract.owner().send());

            //Load contract with read and write block data with default gas-limit 3000000.
            contract = ContractLoader.getContract(
                    PRIVATE_KEY,
                    CONTRACT_ADDRESS,
                    StandardTokenContract.class);
            System.out.println(contract.owner().send());

            //Load contract with read and write block data with customize gas-limit.
            contract = ContractLoader.getContract(
                    PRIVATE_KEY,
                    Convert.toWei("3000000", Convert.Unit.WEI).toBigInteger(),
                    CONTRACT_ADDRESS,
                    StandardTokenContract.class);
            System.out.println(contract.owner().send());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5. References

<Installing the Solidity Compiler> : https://docs.soliditylang.org/en/v0.8.14/installing-solidity.html

<Command line tools> : https://docs.web3j.io/4.8.7/command_line_tools/

<Construction and Deployment> : https://docs.web3j.io/4.8.7/smart_contracts/construction_and_deployment/#solidity-smart-contract-wrappers

### Java Unirest Library Usage and Documentation The Unirest library simplifies HTTP requests in Java applications by providing a fluent API that is both intuitive and powerful. This section covers how to integrate and use the Unirest library within a Java project. #### Adding Dependency To include Unirest in a Maven-based project, add this dependency to `pom.xml`: ```xml <dependency> <groupId>com.konghq</groupId> <artifactId>unirest-java</artifactId> <version>3.13.7</version> </dependency> ``` For Gradle projects, insert the following line into your build file: ```groovy implementation &#39;com.konghq:unirest-java:3.13.7&#39; ``` #### Basic GET Request Example Creating simple GET requests becomes straightforward using Unirest&#39;s methods: ```java import kong.unirest.Unirest; import kong.unirest.HttpResponse; import kong.unirest.JsonNode; public class Main { public static void main(String[] args) { HttpResponse<JsonNode> response = Unirest.get("https://jsonplaceholder.typicode.com/posts/1") .asJson(); System.out.println(response.getBody()); } } ``` This code snippet demonstrates fetching JSON data from an external service and printing it out directly[^1]. #### Making POST Requests Sending form parameters or JSON payloads can be done easily through Unirest’s fluent interface: ```java HttpResponse<String> response = Unirest.post("http://httpbin.org/post") .field("parameter", "value") // For sending form fields .body("{\"example\":\"json\"}") // Or send raw JSON bodies .asString(); System.out.println(response.getStatus()); // Print status code of request ``` In addition to these basic operations, Unirest supports more advanced features like asynchronous calls, custom headers, query strings, multipart uploads, etc., making web interactions much simpler compared to traditional approaches such as URLConnection or Apache HttpClient. --related questions-- 1. How does one handle exceptions when performing network operations with Unirest? 2. What are some best practices for managing connections while using Unirest in production environments? 3. Can you provide examples on handling different types of responses (JSON, XML)? 4. Is there support for OAuth authentication mechanisms within Unirest? If so, how would one implement them? 5. Are there any performance considerations developers should keep in mind when choosing between synchronous versus asynchronous execution models?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值