1、關(guān)于開(kāi)發(fā)環(huán)境搭建配置等可參考之前的文章 2、部署合約代碼erc20.js
const hre = require("hardhat");
async function main() {
const CONTRACT = await hre.ethers.getContractFactory("ERC20");
const contract = await CONTRACT.deploy();
await contract.init("ERC20Name","ERC20Symbol");
console.log("name:",contract.name(),"symbol:",contract.symbol());
await contract.deployed();
console.log(`contract deployed to ${contract.address}`);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
3、啟動(dòng)并上鏈
#切換到智能合約項(xiàng)目位置
npx hardhat node
#新開(kāi)一個(gè)窗口,確保localhost已經(jīng)在hardhat.config.js中配置了,可查看第一步鏈接對(duì)照
npx hardhat run scripts/erc.js --network localhost
4、新建一個(gè)文件夾,存放go項(xiàng)目,完成mod初始化等
完整go項(xiàng)目文件目錄
5、拷貝智能合約compile產(chǎn)生的ABI,在新文件夾中新建一個(gè)erc20.json文件
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-503299.html
?
6、安裝abigen
go get github.com/ethereum/go-ethereum
#切換路徑 cd $GOPATH/pkg/mod/github.com/ethereum/go-ethereum@v1.10.25
sudo make && make devtools
#測(cè)試安裝
abigen --help
7、將ABI生成GO文件
abigen --abi erc20.json -pkg json -type erc20 --out erc20.go
8、編寫調(diào)用文件 main.go
package main
import (
"context"
"crypto/ecdsa"
"fmt"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"math/big"
"mysolidity/json"
)
func main() {
//合約地址
contractAddress := "0x5FbDB2315678afecb367f032d93F642f64180aa3"
//連接本地的以太坊私鏈(一定要保證本地以太坊私鏈已經(jīng)啟動(dòng))
conn, err := ethclient.Dial("http://127.0.0.1:8545")
fmt.Println("connect to local node...", conn)
if err != nil {
fmt.Errorf("could not connect to local node: %v", err)
return
}
//創(chuàng)建合約
erc20, err := json.NewErc20(common.HexToAddress(contractAddress), conn)
if err != nil {
fmt.Errorf("failed to instantiate a Token contract: %v", err)
return
}
fmt.Println("contract token:", erc20)
//調(diào)用合約查詢方法
name, err := erc20.Name(&bind.CallOpts{
Pending: false,
From: common.Address{},
BlockNumber: nil,
Context: nil,
})
if err != nil {
fmt.Errorf("name:%v", err)
return
}
symbol, err := erc20.Symbol(&bind.CallOpts{
Pending: false,
From: common.Address{},
BlockNumber: nil,
Context: nil,
})
if err != nil {
fmt.Errorf("name:%v", err)
return
}
fmt.Println("name:", name, "symbol:", symbol)
//查詢第一個(gè)賬戶余額
b, err := erc20.BalanceOf(&bind.CallOpts{
Pending: false,
From: common.Address{},
BlockNumber: nil,
Context: nil,
}, common.HexToAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"))//啟動(dòng)node默認(rèn)生成的第1個(gè)賬戶地址
if err != nil {
fmt.Errorf("BalanceOf:%v", err)
return
}
fmt.Println("first balance:", b)
第一個(gè)賬戶給第二個(gè)賬戶轉(zhuǎn)賬
//私鑰,需要生成簽名
privateKey, err := crypto.HexToECDSA("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80")//私鑰注意去掉ox,這是啟動(dòng)node默認(rèn)生成的第1個(gè)賬戶的私鑰
if err != nil {
fmt.Errorf("err:%v\n", err)
return
}
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
fmt.Errorf("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
return
}
fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
nonce, err := conn.PendingNonceAt(context.Background(), fromAddress)
if err != nil {
fmt.Errorf("%v", err)
return
}
gasPrice, err := conn.SuggestGasPrice(context.Background())
if err != nil {
fmt.Errorf("%v", err)
return
}
//chainID
id, err := conn.ChainID(context.Background())
if err != nil {
return
}
fmt.Println("chainID:", id)
auth, _ := bind.NewKeyedTransactorWithChainID(privateKey, id)
auth.Nonce = big.NewInt(int64(nonce))
auth.Value = big.NewInt(10)
auth.GasLimit = uint64(300000)
auth.GasPrice = gasPrice
tx, err := erc20.Transfer(&bind.TransactOpts{
Signer: auth.Signer,
From: fromAddress,
GasLimit: auth.GasLimit,
GasPrice: auth.GasPrice,
Context: nil,
}, common.HexToAddress("0x70997970C51812dc3A010C7d01b50e0d17dc79C8"), big.NewInt(8))
if err != nil {
fmt.Errorf("transfer:%v", err)
return
}
fmt.Println("tx.GasPrice():", tx.GasPrice())
//查詢兩個(gè)賬戶余額
b, err = erc20.BalanceOf(&bind.CallOpts{From: fromAddress}, common.HexToAddress("0x70997970C51812dc3A010C7d01b50e0d17dc79C8"))//啟動(dòng)node默認(rèn)生成的第2個(gè)賬戶地址
if err != nil {
fmt.Errorf("BalanceOf:%v", err)
return
}
fmt.Println("second balance:", b)
b, err = erc20.BalanceOf(&bind.CallOpts{From: fromAddress}, fromAddress)
if err != nil {
fmt.Errorf("BalanceOf:%v", err)
return
}
fmt.Println("first balance:", b)
}
9、查詢事件日志(完整開(kāi)發(fā)的一般流程,在鏈端開(kāi)發(fā)智能合約后,由前端使用web3.js等進(jìn)行交互,后端通過(guò)查詢事件日志修改數(shù)據(jù)庫(kù)信息展示)
package main
import (
"context"
"fmt"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"math/big"
"mysolidity/json"
)
func main() {
//合約地址
contractAddress := common.HexToAddress("0x5FbDB2315678afecb367f032d93F642f64180aa3")
//websocket監(jiān)聽(tīng)
client, err := ethclient.Dial("ws://127.0.0.1:8545/ws")
if err != nil {
fmt.Errorf("could not connect to local node: %v", err)
return
}
query := ethereum.FilterQuery{
FromBlock: big.NewInt(1), //生產(chǎn)環(huán)境中,從0開(kāi)始,查詢后修改區(qū)塊記錄,下一次就從后一個(gè)有記錄的區(qū)塊數(shù)開(kāi)始
ToBlock: big.NewInt(100),
Addresses: []common.Address{
contractAddress,
},
}
erc20, _ := json.NewErc20(contractAddress, client)
logs, err := client.FilterLogs(context.Background(), query)
if err != nil {
fmt.Errorf("err:%v\n", err)
return
}
for _, vLog := range logs {
if len(vLog.Topics) == 0 {
continue
}
event := vLog.Topics[0].Hex()
if event == TransferEvent() { //對(duì)對(duì)應(yīng)的事件進(jìn)行對(duì)應(yīng)的處理
fmt.Println(vLog.Data)
data, err := erc20.ParseTransfer(vLog)
if err != nil {
fmt.Errorf("err:%v\n", err)
continue
}
fmt.Println(data.From.Hex(), data.To.Hex(), data.Value.Int64(), data.Raw.Data)
}
}
}
func TransferEvent() string {
event := crypto.Keccak256Hash([]byte("Transfer(address,address,uint256)")).Hex()
return event
}
10、測(cè)試結(jié)果(main.go為最后一次運(yùn)行結(jié)果)
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-503299.html
?
到了這里,關(guān)于在本地以太坊私鏈上,使用go調(diào)用智能合約,獲取事件日志的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!