moecat

moecat

摸鱼大师

web3j學習(1)

本文源代碼見 https://github.com/pigeon2049/planet-universal

作為一個寫 java 的全棧開發,sodility 語言似乎讓人很難下手,所以先從熟悉的領域入手

web3j

起手一個傳統 springboot maven 項目,引用 web3j 依賴

<dependency>
    <groupId>org.web3j</groupId>
    <artifactId>core</artifactId>
    <version>${web3j.version}</version>
</dependency>
<dependency>
    <groupId>org.web3j</groupId>
    <artifactId>contracts</artifactId>
    <version>${web3j.version}</version>
</dependency>

為了快速開發學習,本機需要安裝 docker

image

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-docker-compose</artifactId>
  <scope>runtime</scope>
  <optional>true</optional>
</dependency>

新版本 springboot 支持集成 docker, 所以沒有安裝環境的過程,直接啟,會得到一個 ipfs kubo 客戶端以及 influxdb 時序數據庫


開始學習:
web3j 需要一個以太坊客戶端節點,可以自己用 geth 搭一個,也可以偷懶使用 cloudflare 提供的公共端口,使用公共端口注意儘量不要使用自己的地址和密鑰與合約交互,容易產生安全問題

application.properties 添加 cloudflare eth gateway

web3j.node.address=https://cloudflare-eth.com/

定義一個配置文件,生成 web3j 的 bean


@Configuration
public class Web3jConfig {

    @Value("${web3j.node.address}")
    private String ethNode;

    @Bean
    public Web3j web3j() throws ExecutionException, InterruptedException {
        Web3j build = Web3j.build(new HttpService(ethNode));
        Web3ClientVersion web3ClientVersion = build.web3ClientVersion().sendAsync().get();
        System.out.println(web3ClientVersion.getWeb3ClientVersion());
        return build;
    }
}

這樣我們就得到了一个可用的 web3j client


接下來簡單寫個獲取以太坊鏈上實時 Gas 費的方法

@Service
public class GasPrice {

    private final Web3j web3j;


    public GasPrice(Web3j web3j) {
        this.web3j = web3j;
    }


    public BigInteger gasGasPrice() throws IOException {

        return web3j.ethGasPrice().send().getGasPrice();
    }



}

是不是很簡單?

但是你就會發現這個單位好像不對,平時看到的是 Gwei
, 換算一下

BigInteger gas = gasPrice.gasGasPrice();
BigDecimal value= BigDecimal.valueOf(gas .longValue() * 0.000000001).setScale(2, RoundingMode.HALF_UP);

保留兩位小數,得到的就是 Gwei 了

簡單寫個定時,每秒獲取一次 Gas 數據存數據庫

@Service
public class UpdateGasPrice implements CommandLineRunner {

    @Value("${influx.url}")
    String url;

    @Value("${influx.token}")
    String token;

    @Value("${influx.org}")
    String org ;

    @Value("${influx.bucket}")
    String bucket ;

    private final GasPrice gasPrice;

    public UpdateGasPrice(GasPrice gasPrice) {
        this.gasPrice = gasPrice;
    }

    @Override
    public void run(String... args) throws Exception {
        InfluxDBClient client = InfluxDBClientFactory.create(url, token.toCharArray(), org, bucket)
                .setLogLevel(LogLevel.BASIC);
        WriteApi writeApi = client.makeWriteApi(WriteOptions.builder().flushInterval(2_000).build());

        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {

                try {
                    BigInteger gas = gasPrice.gasGasPrice();
                    if (gas!=null){
                        BigDecimal value= BigDecimal.valueOf(gas.longValue() * 0.000000001).setScale(2, RoundingMode.HALF_UP);
                        Point point = Point
                                .measurement("eth")
                                .addField("gas", gas.longValue())
                                .addField("gasGwei", value)
                                .time(Instant.now(), WritePrecision.S);

                        System.out.println("Produced DataPoint: " + point.toLineProtocol());

                        writeApi.writePoint(point);
                    }


                } catch (IOException ignored) {}

            }
        }, 0, 1000);

        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("Close Client and Producer");
            timer.cancel();
            client.close();
        }));
    }
}

運行代碼

image

打開http://localhost:8086
進入 influxdb 的管理網頁,密碼寫在 env 裡

可以看到已經開始寫入 gas 數據了
image


獲取地址以太坊餘額

以太坊鏈上就很簡單


  public BigDecimal getBalance(String address) throws IOException {
      BigInteger balance = web3j.ethGetBalance(address, DefaultBlockParameterName.LATEST).send().getBalance();
      BigDecimal ether = Convert.fromWei(String.valueOf(balance), Convert.Unit.ETHER);
      System.out.println(address+" balance:"+ether.toString());
      return  ether;
  }

獲取 Erc20 代幣餘額


public BigDecimal getErc20Balance(String address,String tokenContractAddress) throws Exception {

        // Use ReadOnlyTransactionManager for read-only operations
        ReadonlyTransactionManager txManager = new ReadonlyTransactionManager(web3j, null);
        DefaultGasProvider gasPriceProvider = new DefaultGasProvider();
        // ERC20 is your generated ERC20 contract wrapper class
        ERC20 contract = ERC20.load(tokenContractAddress, web3j, txManager, gasPriceProvider);

        // Call the balanceOf function on the ERC-20 contract
        BigInteger balance = contract.balanceOf(address).send();
        BigDecimal ether = Convert.fromWei(String.valueOf(balance), Convert.Unit.ETHER);
        System.out.println("Balance of " + address + ": " + ether);

        return ether;
    }

本次學習了簡易的鏈上操作,只是簡易讀取
後續加深學習合約交互

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。