FunTester Ethereum 第一笔转账

FunTester · 2023年08月14日 · 2829 次阅读

大概是个反射弧巨长,区块链的概念火了这么久,最近才开始学习区块链相关的技术。基础概念学完了,朋友推荐了宇宙第一链Ethereum。经过了周末的学习,终于完成了第一个目标:第一笔转账。

分享一下学习过程和成果,仅供参考。文中涉及的知识均来源于官方文档,地址可以自行搜索。文档有中文版本,但是在代码实践部分还是英文居多。建议初学者把概念性的文档也看一遍,不要直接上手代码。

测试链

首先呢,我们需要在本地搭建一条测试链,就好像 HTTP 接口测试,我们需要一个本地的测试服务器一样。这个 po 一下官方提醒:


在官方给出的开发工具中,我选择了`Ganache`,无他,因为它排在第一位。可以部署测试链,部署智能合约,完全满足了我的需求。

安装同其他软件,然后启动就可以界面:

![安装页面](http://pic.automancloud.com/WX20230812-214247.png)

对于新手而言,选择`QUICKSTART`即可,就可以看到主页面。这里就不放图片占用篇幅了。启动成功后你就得到一个本地服务的IP和端口,这个就是代码中的`host`值。关于如何获取主网的查询的`host`这块,我建议小白先跳过,没必要在本地搞一个`Ethereum`的客户端。

# 创建Java项目

由于我习惯用了Java,所以先从Java开始。当然后面等我熟练了之后还是会尝试使用Groovy实现。后期计划用Golang再写一遍,这里不多说了。

我用了Java依赖`Web3j`,就我看到的资料很多`jsonrpc`的实现,本质上还是HTTP的请求。本来想着用`FunTester`框架实现。但是目下的场景不太允许我这个区块链小白这么搞。

依赖配置:

```XML
        <dependency>
            <groupId>org.web3j</groupId>
            <artifactId>core</artifactId>
            <version>4.3.0</version>
        </dependency>

然后需要个类和main方法,其他无。

验证 Demo

当准备工作就绪,我们编写一些代码调用Ethereum的 API 验证本地测试链是否有效。

import com.funtester.frame.SourceCode;  
import org.web3j.protocol.Web3j;  
import org.web3j.protocol.core.methods.response.EthProtocolVersion;  
import org.web3j.protocol.http.HttpService;  

import java.io.IOException;  

public class Demo extends SourceCode {  

    static Web3j drive = Web3j.build(new HttpService("http://127.0.0.1:7545"));  

    public static void main(String[] args) throws IOException {  
        EthProtocolVersion send = drive.ethProtocolVersion().send();  
        output(parse(send));  
    }  

}

当控制台输出一下格式信息,表示环境搭建工作已经完成了。

~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~
♨ ♨ {
♨ ♨ ① ➤ "result":"0x3f",
♨ ♨ ① ➤ "protocolVersion":"0x3f",
♨ ♨ ① ➤ "id":0,
♨ ♨ ① ➤ "jsonrpc":"2.0"
♨ ♨ }
~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~

转账

Ethereum的 API 很多,Web3j都有对应的实现方法,虽然文档写测试链公共不全,但是就我目前使用来看,用来学习足够,没有遇到缺失的功能。

账号之前的转账是个非常重要的 API,相比其他查询 API 也是比较麻烦的,因为涉及到签名加密。PS:有文档写Ganache允许无签名转账,这个我没试过,毕竟将来是要去主网冲浪的。

下面是转账的 Demo,其中 key 均为测试链上测试账号的,可以通过Ganache页面上小钥匙按钮获得。

package com.funtester.ethereum;

import com.funtester.frame.SourceCode;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.response.*;
import org.web3j.protocol.http.HttpService;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;

import java.io.IOException;
import java.math.BigInteger;
import java.util.Optional;

public class Demo extends SourceCode {

    static Web3j drive = Web3j.build(new HttpService("http://127.0.0.1:7545"));

    public static void main(String[] args) throws IOException, InterruptedException {
        String privateKey = "0x04c02dc2381e1f69a274fa7cc4851c9eb01358fae8753dd4273014b43e34ab0c";
        Credentials credentials = Credentials.create(privateKey);
        EthGetTransactionCount ethGetTransactionCount = drive.ethGetTransactionCount(credentials.getAddress(), DefaultBlockParameterName.LATEST).send();
        BigInteger nonce = ethGetTransactionCount.getTransactionCount();
        String recipientAddress = "0x9483df5Bb8183548B4D7eb66B44C41FccD7c40A6";
        BigInteger value = Convert.toWei("1", Convert.Unit.ETHER).toBigInteger();
        BigInteger gasLimit = BigInteger.valueOf(22100);
        BigInteger gasPrice = Convert.toWei("11", Convert.Unit.GWEI).toBigInteger();
        RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
                nonce,
                gasPrice,
                gasLimit,
                recipientAddress,
                value);
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signedMessage);
        EthSendTransaction ethSendTransaction = drive.ethSendRawTransaction(hexValue).send();
        String transactionHash = ethSendTransaction.getTransactionHash();
        Optional<TransactionReceipt> transactionReceipt = null;
        do {
            EthGetTransactionReceipt ethGetTransactionReceiptResp = drive.ethGetTransactionReceipt(transactionHash).send();
            transactionReceipt = ethGetTransactionReceiptResp.getTransactionReceipt();
            Thread.sleep(3000);
        } while (!transactionReceipt.isPresent());
        System.out.println("deal confirm");
    }

}

后面循环等待响应写得不够优雅,等熟练了封装一个趁手的方法。

控制台输出deal confirm的话,说明转账已经被确认了。可以去Ganache确认一下余额是否正确。当然可以通过Ethereum的 API 查询对应账户的余额前后变化量是否与预期一致。

年轻人的第一笔Ethereum转账

年轻人的第一笔Ethereum转账

年轻人的第一笔Ethereum转账已经完成。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册