go-ethereum教程

2025-04-12

Golang Ethereum教程 完整代码: https://github.com/mazezen/learn/tree/master/01-part-eth-ehereum

动动手指,欢迎点个⭐️

准备

  1. 注册 INFURA账号,以太坊API和网关服务.会提供需要用的节点地址
  2. 安装 ganache-cli , 可以在本机跑起来一个本地网络,并提供10个地址和私钥,和用于测试的gas费. 每个地址有100ETH
  3. 测试网水龙头领取eth sepolia测试币

安装go-ethereum依赖

go get -d github.com/ethereum/go-ethereum/...

教程

1.获取区块高度.

# 连接服务 
ethclient.DialContext(context.Background(), url)
if err != nil {
    log.Fatalf("failed to connect to infura: %v", err)
}

# 拿高度
client.BlockByNumber(context.Background(), nil)
if err != nil {
    log.Fatalf("failed to get block number: %v", err)
}

url: 节点地址.用的哪个网络就填写哪个网络的地址. 比如主网, 测试网,或者使用本地网络节点

2. 获取Address eth余额

ethclient.DialContext(context.Background(), url)

addr := common.HexToAddress("0xD6c57F704B9dBD6b9B9700cc5cD9f0e88C217E7D")
balanceAt, err := client.BalanceAt(context.Background(), addr, nil)
if err != nil {
    log.Fatalf("failed to get balance of %v: %v", addr, err)
}
// 单位是WEI
fmt.Println(balanceAt)

// 科学计数表示法
fBalance := new(big.Float)
fBalance.SetString(balanceAt.String())
fmt.Println(fBalance)


value := new(big.Float).Quo(fBalance, big.NewFloat(math.Pow10(18)))
// 单位是eth
fmt.Println(value)
100000000000000000000
1e+20
100

3. 创建地址

// 生成私钥
pvK, err := crypto.GenerateKey()
if err != nil {
    log.Fatal(err)
}
ecdsa := crypto.FromECDSA(pvK)
encode := hexutil.Encode(ecdsa)

// 私钥生成公钥
crypto.FromECDSAPub(&pvK.PublicKey)

// 公钥派生出地址
crypto.PubkeyToAddress(pvK.PublicKey).Hex()

4. 创建钱包

key := keystore.NewKeyStore("./wallet", keystore.StandardScryptN, keystore.StandardScryptP)
password := "password"
a, err := key.NewAccount(password)
if err != nil {
    log.Fatal(err)
}
fmt.Println(a.Address)

会在生产一个wallet文件夹,存放着钱包的信息

5. 解析钱包,拿到私钥,公钥 和地址

by, err := os.ReadFile("./wallet/file")
if err != nil {
    log.Fatalf("failed to read wallet: %v", err)
}
pvk, err := keystore.DecryptKey(by, password)
if err != nil {
    log.Fatalf("failed to decrypt key: %v", err)
}
pData := crypto.FromECDSA(pvk.PrivateKey)
fmt.Println(hexutil.Encode(pData))

pData = crypto.FromECDSAPub(&pvk.PrivateKey.PublicKey)
fmt.Println(hexutil.Encode(pData))

fmt.Println(crypto.PubkeyToAddress(pvk.PrivateKey.PublicKey).Hex())

6. 获取地址剩余的eth

ethclient.Dial(url)
if err != nil {
    log.Fatal(err)
}
add1 := common.HexToAddress("0x483Df743a6521F2cbd6Ce68Cca1121B95e09679a")
add2 := common.HexToAddress("352da91c8901722f424d00a6e1eba8297074262d")
fmt.Println(add1)
fmt.Println(add2)
balanceAt, err := client.BalanceAt(context.Background(), add1, nil)
if err != nil {
    log.Fatal(err)
}
fmt.Println(balanceAt.String())

balanceAt, err = client.BalanceAt(context.Background(), add2, nil)
if err != nil {
    log.Fatal(err)
}
fmt.Println(balanceAt.String())

代码中的两个地址用的是ganache-cli本地网络供的地址. url为本地网络地址 也可以使用第四步,创建钱包.去测试网水龙头领取测试等

7. 交易(Transfer)

// 链接网络
ethclient.Dial(url)

// 获取余额
client.BalanceAt(context.Background(), add1, nil)
client.BalanceAt(context.Background(), add2, nil)

// 拿到nonce
client.PendingNonceAt(context.Background(), add1)
// 拿gas费
client.SuggestGasPrice(context.Background())

// 创建交易数据,交易1个ETH
transaction := types.NewTx(&types.LegacyTx{
    Nonce:    nonceAt,
    GasPrice: gasPrice,
    Gas:      21000,
    To:       &add2,
    Value:    big.NewInt(1000000000000000000),
})
// 获取chaninID
client.NetworkID(context.Background())


pvkStr := "6ee4e3758996db5d5c3bab59c778c133637d99f7774a49cd831cdb13529a9c60"
privateKey, err := crypto.HexToECDSA(pvkStr)
if err != nil {
    log.Fatal(err)
}

tx, err := types.SignTx(transaction, types.NewEIP155Signer(chainID), privateKey)
if err != nil {
    log.Fatal(err)
}
fmt.Println(tx.Hash().Hex())

此次交易用的是ganache-cli 跑的本地网络 两个地址用的也是本地网络提供的地址.每个地址有100ETH

完整代码: https://github.com/mazezen/learn/tree/master/01-part-eth-ehereum