使用Java+Web3j和Ethereum網路互動(一):獲取Ethereum資訊

觸不可及`發表於2022-06-24

簡介

web3j是一個高度模組化,響應式的,型別安全的Java和Android庫,可以用於和以太坊網路上的節點以及智慧合約進行互動
Web3j使你與以太坊網路進行互動,不需要額外的去寫與以太坊平臺互動的程式碼開銷。

特性

  • 完整地實現了Ethereum中HTTP和IPC上的JSON-RPC客戶端API
  • 支援ethereum錢包
  • 可以自動生成封裝好的Java型別的智慧合約(支援Solidity和Truffle定義的格式),可以透過Java程式碼進行合約的建立,部署,以及呼叫。
  • 可以新增過濾器的響應式函式API
  • 支援Ethereum Name Service(ENS)
  • 支援個人建立的Ethereum網路和個人的Geth客戶端API
  • 支援Alchemy和Infura,所以無需自己執行以太坊客戶端
  • 支援ERC20和ERC721 Token標準
  • 包括上述許多場景的全面的整合測試
  • 命令列工具
  • 可適配Android
  • 可以透過web3j-quorm支援JP Morgan的Quorum

依賴

Web3j具有五個執行時依賴

使用SpringBoot+Web3j搭建環境

2.1 Etherum環境

透過Web3j與以太坊進行互動前提條件是需要有Ethereum環境,搭建Ethherum環境可以透過多種方式,本文僅列出常用的兩個:

  • Ganache
  • Docker

新建Springboot專案

首先在https://start.spring.io/ 上面初始化一個Springboot專案,匯入Idea,或者直接在Idea上面建立。

匯入Web3j

開啟pom.xml檔案,新增以下依賴:

        <!-- https://mvnrepository.com/artifact/org.web3j/core -->
        <dependency>
            <groupId>org.web3j</groupId>
            <artifactId>web3j-spring-boot-starter</artifactId>
            <version>4.0.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.web3j/core -->
        <dependency>
            <groupId>org.web3j</groupId>
            <artifactId>core</artifactId>
            <version>4.8.4</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.9.0</version>
        </dependency>

基本配置

接下來開啟application.properties檔案,新增以下內容:

# 應用名稱
spring.application.name=ethereum-client
#訪問埠
server.port=8081
#以太坊互動地址 如果以太坊環境搭建在本地就locallhost,否則使用對應的ip地址,埠預設使用8545
web3j.client-address=http://localhost:8545

基本使用

必要的配置已完成,接下來可以與Etherum互動了。這裡列出常見的幾個功能,文章最後給出完整的程式碼。

獲取最新的區塊號

EthBlockNumber ethBlockNumber = web3j.ethBlockNumber().sendAsync().get();
BigInteger blockNumber = ethBlockNumber.getBlockNumber();

獲取所有賬戶資訊

EthAccounts ethAccounts = web3j.ethAccounts().sendAsync().get();
List<String> accounts = ethAccounts.getAccounts();

查詢Gas價格

EthGasPrice ethGasPrice = web3j.ethGasPrice().sendAsync().get();
BigInteger gasPrice = ethGasPrice.getGasPrice();

獲取ChainId

EthChainId ethChainId = web3j.ethChainId().sendAsync().get();
BigInteger chainId = ethChainId.getChainId();

獲取CoinBase

EthCoinbase ethCoinbase = web3j.ethCoinbase().sendAsync().get();
String coinBase = ethCoinbase.getAddress();

根據區塊號獲取區塊資訊

DefaultBlockParameterNumber defaultBlockParameterNumber = new DefaultBlockParameterNumber(blockNumber);
EthBlock ethBlock = web3j.ethGetBlockByNumber(defaultBlockParameterNumber,true).sendAsync().get();
EthBlock.Block block = ethBlock.getBlock();

根據區塊號獲取當前區塊所有交易資訊

DefaultBlockParameterNumber defaultBlockParameterNumber = new DefaultBlockParameterNumber(blockNumber);
EthBlock ethBlock = web3j.ethGetBlockByNumber(defaultBlockParameterNumber,true).sendAsync().get();
List<EthBlock.TransactionResult> transactionResults = ethBlock.getBlock().getTransactions();

根據交易雜湊值獲取交易資訊

EthTransaction transaction = web3j.ethGetTransactionByHash(txHash).sendAsync().get();
Optional<Transaction> optionalTransaction = transaction.getTransaction();

賬戶相關

還可以透過私鑰或者Key檔案查詢當前賬戶下的Ether餘額。

查詢Ether餘額

BigInteger blockNumber = web3j.ethBlockNumber().sendAsync().get().getBlockNumber();
DefaultBlockParameterNumber defaultBlockParameterNumber = new DefaultBlockParameterNumber(blockNumber);
//根據請求引數獲取餘額
EthGetBalance ethGetBalance  = web3j.ethGetBalance(credentials.getAddress(),defaultBlockParameterNumber).sendAsync().get();

原始碼

/**
 * @description 獲取區塊鏈資訊
 * @author newonexd
 * @date 2022/6/22 21:14
 */
@RestController
@RequestMapping("/chainInfo")
public class BlockChainInfoController {

    private static final Logger logger = LoggerFactory.getLogger(BlockChainInfoController.class);


    @Autowired
    private Web3j web3j;

    /**
     * @description 獲取最新的區塊號
     * @author newonexd
     * @date 2022/6/22 21:11
     *
     * * @return BigInteger
     */
    @GetMapping("/blockNumber")
    public BigInteger doGetLatestBlockNumber()throws Exception{
        EthBlockNumber ethBlockNumber = web3j.ethBlockNumber().sendAsync().get();
        BigInteger blockNumber = ethBlockNumber.getBlockNumber();
        logger.info("BlockNumber: {}",blockNumber);
        return blockNumber;
    }

    /**
     * @description 獲取所有賬戶
     * @author newonexd
     * @date 2022/6/22 21:11
     *
     * * @return List<String>
     */
    @GetMapping("/accounts")
    public List<String> doGetAllAccounts()throws Exception{
        EthAccounts ethAccounts = web3j.ethAccounts().sendAsync().get();
        List<String> accounts = ethAccounts.getAccounts();
        logger.info("Accounts: {}",accounts);
        return accounts;
    }

    /**
     * @description 獲取Gas價格
     * @author newonexd
     * @date 2022/6/22 21:11
     *
     * * @return BigInteger
     */
    @GetMapping("/gasPrice")
    public BigInteger doGetEthGasPrice()throws Exception{
        EthGasPrice ethGasPrice = web3j.ethGasPrice().sendAsync().get();
        BigInteger gasPrice = ethGasPrice.getGasPrice();
        logger.info("Ethereum Gas Price: {}",gasPrice);
        return gasPrice;
    }

    /**
     * @description 獲取鏈Id
     * @author newonexd
     * @date 2022/6/22 21:12
     *
     * * @return BigInteger
     */
    @GetMapping("/chainId")
    public BigInteger doGetChainId()throws Exception{
        EthChainId ethChainId = web3j.ethChainId().sendAsync().get();
        BigInteger chainId = ethChainId.getChainId();
        logger.info("Ethereum Chain Id: {}",chainId);
        return chainId;
    }


    /**
     * @description 獲取CoinBase
     * @author newonexd
     * @date 2022/6/22 21:12
     *
     * * @return String
     */
    @GetMapping("/coinbase")
    public String doGetCoinBase()throws Exception{
        EthCoinbase ethCoinbase = web3j.ethCoinbase().sendAsync().get();
        String coinBase = ethCoinbase.getAddress();
        logger.info("Ethereum CoinBase Address: {}",coinBase);
        return coinBase;
    }


    /**
     * @description 根據區塊號獲取區塊資訊
     * @author newonexd
     * @date 2022/6/22 21:12
     * @param blockNumber  區塊號
     * @return String
     */
    @GetMapping("/getBlockInfo")
    public String doGetAll(@RequestParam(value="blockNumber")Long blockNumber)throws Exception{
        DefaultBlockParameterNumber defaultBlockParameterNumber = new DefaultBlockParameterNumber(blockNumber);
        EthBlock ethBlock = web3j.ethGetBlockByNumber(defaultBlockParameterNumber,true).sendAsync().get();
        EthBlock.Block block = ethBlock.getBlock();
        Gson gson = new Gson();
        String info = gson.toJson(block);
        logger.info(info);
        return info;
    }


    /**
     * @description 根據區塊號獲取所有交易
     * @author newonexd
     * @date 2022/6/22 21:13
     * @param blockNumber 區塊號
     * @return String
     */
    @GetMapping("/getTransactionByBlockNumber")
    public String doGetTransactionInfoByBlockNumber(@RequestParam(value="blockNumber")Long blockNumber)throws Exception{
        DefaultBlockParameterNumber defaultBlockParameterNumber = new DefaultBlockParameterNumber(blockNumber);
        EthBlock ethBlock = web3j.ethGetBlockByNumber(defaultBlockParameterNumber,true).sendAsync().get();
        List<EthBlock.TransactionResult> transactionResults = ethBlock.getBlock().getTransactions();
        List<Transaction> txInfos = new ArrayList<>();

        transactionResults.forEach(txInfo->{
            Transaction transaction = (Transaction)txInfo;
            txInfos.add(transaction);
        });
        Gson gson = new Gson();
        String transactionInfo = gson.toJson(txInfos);
        logger.info(transactionInfo);
        return transactionInfo;
    }


    /**
     * @description 根據交易雜湊值獲取交易資訊
     * @author newonexd
     * @date 2022/6/22 21:13
     * @param txHash 交易雜湊值
     * @return String
     */
    @GetMapping("/getTransactionInfoByHash")
    public String doGetTransactionInfoByHash(@RequestParam(value="txHash")String txHash)throws Exception{
        EthTransaction transaction = web3j.ethGetTransactionByHash(txHash).sendAsync().get();
        Optional<Transaction> optionalTransaction = transaction.getTransaction();
        StringBuilder txInfo = new StringBuilder();
        if(optionalTransaction.isPresent()){
            Transaction transactionInfo = optionalTransaction.get();
            Gson gson = new Gson();
            txInfo.append(gson.toJson(transactionInfo));
        }
        logger.info(txInfo.toString());
        return txInfo.toString();
    }
}

相關文章