本文源代碼見 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
<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();
}));
}
}
運行代碼
打開http://localhost:8086
進入 influxdb 的管理網頁,密碼寫在 env 裡
可以看到已經開始寫入 gas 數據了
獲取地址以太坊餘額
以太坊鏈上就很簡單
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;
}
本次學習了簡易的鏈上操作,只是簡易讀取
後續加深學習合約交互