golang与以太坊交互

文章目录

  • golang与以太坊交互
    • 什么是go-ethereum
    • 与节点交互前的准备
    • 使用golang与以太坊区块链交互
    • 查询账户的余额
    • 使用golang生成以太坊账户
    • 使用golang生成以太坊钱包
    • 使用golang在账户之间转移eth
    • 安装使用solc和abigen
    • 生成bin和abi文件
    • 生成go文件
    • 使用golang在测试网上部署智能合约
    • 使用goalng与智能合约进行交互
    • 使用golang在Etherscan上验证合约

golang与以太坊交互

阅读此文章前,需要你了解go,solidity,ethereum相关基础知识。

Golang基础入门-CSDN博客

go语言–区块链学习(三)_go区块链合约-CSDN博客

MetaMask安装及使用(全网最全!!!)_matemask-CSDN博客

Solidity基础(详细易懂!!!)_solidity教程-CSDN博客

在以太坊测试网上部署合约_将智能合约部署至以太坊测试网-CSDN博客

此篇文章参考于01-Interact with Ethereum blockchain using Golang (youtube.com),博主在视频代码的基础上进行了些改进,修改了一些被弃用的包和函数,并结合自己的理解写下了这篇博客。

什么是go-ethereum

Geth (go-ethereum) 是以Go语言实现的以太坊——通往去中心化网络的门户。

自始至终,Geth 一直是以太坊的核心部分。作为最早的以太坊实现之一,Geth 经历了最多的实战检验和测试。

Geth 是一个以太坊执行客户端,负责处理交易、智能合约的部署和执行,内置了被称为以太坊虚拟机的嵌入式计算机。将 Geth 与共识客户端一起运行,可以将一台计算机转变为以太坊节点。

与节点交互前的准备

前面提到,将 Geth 与共识客户端一起运行,可以将一台计算机转变为以太坊节点,这样做,可以为我们带来什么?

运行自己的节点使您能够以真正私密、自给自足和无需信任的方式使用以太坊。您无需信任接收到的信息,因为可以通过您的 Geth 实例自行验证数据。

这样你就可以直接利用自己的节点提供的 rpc 地址直接与以太坊网络进行交互了。但是,对于一般的个人开发者来说,运营一台以太坊节点服务器,成本可能有些许高昂。

并且,由于高昂的 gas 费用,我们在开发过程中的测试,不可能是在以太坊主网上测试的。我们在实际开发过程中,可以启动本地 Geth 测试网或者用 Ganache 快速启动一条测试链,做本地开发测试,但是这并不能涵盖所有的以太坊网络上的可能性。

为了模拟更真实的以太坊网络环境,帮助我们更好地去构建我们的 dapp,我们可以选择与以太坊测试网络进行交互,做开发测试。

如何与测试网交互?同样,将自己的设备作为以太坊节点(测试网节点)还是过于繁琐,下面介绍一项第三方托管服务。

Infura 是一项托管服务,提供安全可靠的访问多种区块链网络的能力,帮助开发者摆脱管理区块链基础设施的复杂性,让他们专注于构建创新的 Web3 应用程序。

Infura 充当了连接应用程序与区块链网络的重要桥梁,为开发者提供强大的API以与区块链进行交互、部署和管理智能合约等功能。无论您是构建去中心化应用程序(Dapp)、加密钱包还是交易所,Infura都提供了必要的基础设施和工具,帮助创建高质量、可靠的 Web3 应用程序。

首先,我们来到 Infura 的官网(不要开代理):Ethereum API | IPFS API & Gateway | ETH Nodes as a Service | Infura

注册登录,选择以太坊服务,选择免费的 Infura 服务。

接下来,会进入到我们的面板,点击 My First Key,查看你的 api 密钥。

请添加图片描述

如果一开始注册过程中未选择以太坊的服务,也不要紧,这里勾选一下就好了,然后点击 Active Endpoints。

请添加图片描述

然后你就可以看到你可以使用的 rpc 地址了,这里我们只需要主网和 sepolia 测试网的就可以了。

在这里插入图片描述

使用golang与以太坊区块链交互

接下来,我们将利用 Infura 提供的 rpc 地址,去获取 sepolia 测试网上当前的区块高度。

代码:

package mainimport ("context""fmt""github.com/ethereum/go-ethereum/ethclient" // 导入以太坊客户端库"log"
)var infuraURL = "https://sepolia.infura.io/v3/********************************" // Infura提供的API URLfunc main() {// 使用Infura URL连接以太坊客户端client, err := ethclient.DialContext(context.Background(), infuraURL)if err != nil {log.Fatalf("Error to create a ether client:%v", err) // 如果连接失败,打印错误并终止程序}defer client.Close() // 程序结束前关闭客户端连接// 获取最新区块block, err := client.BlockByNumber(context.Background(), nil)if err != nil {log.Fatalf("Error to get a block:%v", err) // 如果获取区块失败,打印错误并终止程序}fmt.Println(block.Number()) // 打印区块号
}

然后我们编译运行一下代码。

在这里插入图片描述

可以看到,区块链浏览器上显示的最后一个区块也是6248296。TESTNET Sepolia (ETH) Blockchain Explorer (etherscan.io)

在这里插入图片描述

查询账户的余额

接下来,我们去获取我们的账户余额,打开我们的metamask,复制我们的账户地址,写入代码,编译运行。

代码:

package mainimport ("context""fmt""github.com/ethereum/go-ethereum/common" // 导入以太坊常用函数库"github.com/ethereum/go-ethereum/ethclient" // 导入以太坊客户端库"log""math""math/big"
)var infuraURL = "https://sepolia.infura.io/v3/********************************" // Infura提供的API URLfunc main() {// 使用Infura URL连接以太坊客户端client, err := ethclient.DialContext(context.Background(), infuraURL)if err != nil {log.Fatalf("Error to create a ether client:%v", err) // 如果连接失败,打印错误并终止程序}defer client.Close() // 程序结束前关闭客户端连接// 要查询余额的以太坊地址addr := "0x****************************************"address := common.HexToAddress(addr)// 获取地址的余额balance, err := client.BalanceAt(context.Background(), address, nil)if err != nil {log.Fatalf("Error to get the balance:%v", err) // 如果获取余额失败,打印错误并终止程序}fmt.Println("The balance:", balance)// 将余额转换为以太单位(从wei到ether)// 1 ether = 10^18 wei// 将balance转换为big.Float类型以处理大数fBalance := new(big.Float)fBalance.SetString(balance.String())// 打印原始的big.Float格式的余额fmt.Println("Balance as big.Float:", fBalance)// 计算以ether为单位的余额balanceEther := new(big.Float).Quo(fBalance, big.NewFloat(math.Pow10(18)))fmt.Println("Balance in ether:", balanceEther)
}

这样,我们就可以看到我们的账户余额了。

在这里插入图片描述

使用golang生成以太坊账户

当您想要创建一个账户时,大多数库会为您生成一个随机的私钥。

私钥由64个十六进制字符组成,并且可以用密码加密。

公钥是使用椭圆曲线数字签名算法从私钥生成的。您可以通过取公钥的 Keccak-256 哈希的最后20个字节并在开头添加 0x 来获得您账户的公共地址。

接下来是使用 golang 生成一个账户的代码。

代码:

package mainimport ("fmt""github.com/ethereum/go-ethereum/common/hexutil" // 导入以太坊的hex编解码包"github.com/ethereum/go-ethereum/crypto" // 导入以太坊的加密库"log"
)func main() {// 生成一个新的以太坊私钥pvk, err := crypto.GenerateKey()if err != nil {log.Fatal(err) // 如果生成私钥时出现错误,打印错误信息并退出程序}// 将私钥转换为字节格式,并以hex编码方式打印出来pData := crypto.FromECDSA(pvk)fmt.Println(hexutil.Encode(pData))// 将公钥部分(从私钥派生而来)转换为字节格式,并以hex编码方式打印出来puData := crypto.FromECDSAPub(&pvk.PublicKey)fmt.Println(hexutil.Encode(puData))// 使用公钥生成对应的以太坊地址,并以hex编码方式打印出来fmt.Println(crypto.PubkeyToAddress(pvk.PublicKey).Hex())
}

获得的账户私钥是可以直接导入你的 metamask 的,不用担心会生成一个被使用过的账户。

(这里的私钥只是作为演示,我是不用的,我没打码,大家不要直接拿来用,造成的财产损失,博主概不负责,大家请妥善保管好自己的私钥)

在这里插入图片描述

在这里插入图片描述

使用golang生成以太坊钱包

除了使用 crypto.GenerateKey() 生成以太坊账户的私钥之外,还有一种更安全的方式,即使用 keystore 库。这个库将账户的私钥安全地存储在操作系统的文件系统中。私钥通常以 JSON 格式编码,并使用密码加密,以确保在存储和传输过程中的安全性。

设计 keystore 库的初衷之一是安全地管理以太坊账户的私钥,并避免将私钥直接硬编码在代码中。直接在代码中使用私钥存在许多安全风险,例如私钥泄露或意外提交到版本控制系统中,这可能导致资产损失或被恶意利用。使用 keystore 可以将私钥安全地存储在操作系统的文件系统中,并使用密码加密,只在必要时才解密和使用私钥,从而增强了私钥管理的安全性。

keystore 库使得以太坊开发者能更便捷地管理私钥和账户,提供了一种安全且标准化的方法来处理与以太坊账户相关的加密操作和文件存储需求。

代码:

package mainimport ("fmt""github.com/ethereum/go-ethereum/accounts/keystore" // 导入以太坊账户管理和密钥存储库"log"
)func main() {// 创建一个新的 keystore 实例,将密钥存储在当前目录下的 "wallet" 文件夹中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.Hex())
}

这样我们就得到了一个加密后的账户,可以看到,在我们的 wallet 文件夹下,有我们的密钥文件。

在这里插入图片描述

因为 goland 默认用 .txt 格式打开这个密钥文件,所以格式不如人意,我们可以在 Settings->File Types->JSON 里面添加文件名通配类型。

UTC--*-*-*T*-*-*.*Z--*
或
UTC--*

在这里插入图片描述

完成之后,可以看到我们的文件显示,已经变成高亮了。

在这里插入图片描述

接下来按住Ctrl+Alt+L,格式化代码,就可以看的更舒服一点了。

在这里插入图片描述

然后,接下来,我们来使用这个密钥文件,从里面拿出我们的私钥、公钥和钱包地址。

代码:

package mainimport ("fmt""github.com/ethereum/go-ethereum/accounts/keystore""github.com/ethereum/go-ethereum/common/hexutil""github.com/ethereum/go-ethereum/crypto""log""os"
)func main() {//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)// 使用已存在的密钥文件进行解密b, err := os.ReadFile("./wallet/UTC--****-**-**T**-**-**.**********--****************************************") // 读取密钥文件if err != nil {log.Fatal(err)}key, err := keystore.DecryptKey(b, password) // 解密密钥文件if err != nil {log.Fatal(err)}// 获取私钥的字节表示,并打印出来pData := crypto.FromECDSA(key.PrivateKey)fmt.Println("Priv", hexutil.Encode(pData))// 获取公钥的字节表示,并打印出来pData = crypto.FromECDSAPub(&key.PrivateKey.PublicKey)fmt.Println("Pub", hexutil.Encode(pData))// 获取以太坊地址,并打印出来fmt.Println("Add", crypto.PubkeyToAddress(key.PrivateKey.PublicKey).Hex())
}

编译运行后我们就可以拿到我们的私钥、公钥和账户地址了。

在这里插入图片描述

使用golang在账户之间转移eth

我们先使用 keystore 创建两个以太坊账户,也可以只创建一个,因为上一步已经创建了一个账户。

代码:

package mainimport ("github.com/ethereum/go-ethereum/accounts/keystore""log"
)func main() {// 用 keystore 创建两个以太坊账户的密钥文件ks := keystore.NewKeyStore("./wallet", keystore.StandardScryptN, keystore.StandardScryptP)_, err := ks.NewAccount("password")if err != nil {log.Fatal(err)}_, err = ks.NewAccount("password")if err != nil {log.Fatal(err)}
}

然后我们使用 metamask 往一个账户里面转点 SepoliaETH。

记得转点,就直接往账户地址里面转就行了。

代码:

package mainimport ("context""fmt""github.com/ethereum/go-ethereum/accounts/keystore""github.com/ethereum/go-ethereum/common""github.com/ethereum/go-ethereum/core/types""github.com/ethereum/go-ethereum/ethclient""log""math/big""os"
)var url = "https://sepolia.infura.io/v3/********************************" // Infura提供的API URLfunc main() {// 客户端连接到以太坊节点client, err := ethclient.Dial(url)if err != nil {log.Fatal(err)}// a1,a2为刚刚创建的两个以太坊账户地址a1 := common.HexToAddress("****************************************")a2 := common.HexToAddress("****************************************")// 查询第一个地址的余额b1, err := client.BalanceAt(context.Background(), a1, nil)if err != nil {log.Fatal(err)}// 查询第二个地址的余额b2, err := client.BalanceAt(context.Background(), a2, nil)if err != nil {log.Fatal(err)}fmt.Println("Balance 1:", b1)fmt.Println("Balance 2:", b2)// 获取第一个地址的待处理交易数量(nonce)nonce, err := client.PendingNonceAt(context.Background(), a1)if err != nil {log.Fatal(err)}// 设置要发送的以太币数量(1 ether = 1000000000000000000 wei)amount := big.NewInt(1000000000000000)// 获取推荐的 gas 价格gasPrice, err := client.SuggestGasPrice(context.Background())if err != nil {log.Fatal(err)}// 创建新的交易tx := types.NewTx(&types.LegacyTx{Nonce:    nonce,To:       &a2,Value:    amount,Gas:      21000,GasPrice: gasPrice,Data:     nil,})// 获取当前链的 IDchainID, err := client.NetworkID(context.Background())if err != nil {log.Fatal(err)}// 从密钥文件中解密私钥b, err := os.ReadFile("./wallet/UTC--****-**-**T**-**-**.**********--****************************************") // 有余额的账户的密钥文件if err != nil {log.Fatal(err)}key, err := keystore.DecryptKey(b, "password")if err != nil {log.Fatal(err)}// 使用私钥对交易进行签名tx, err = types.SignTx(tx, types.NewEIP155Signer(chainID), key.PrivateKey)if err != nil {log.Fatal(err)}// 发送交易到以太坊网络err = client.SendTransaction(context.Background(), tx)if err != nil {log.Fatal(err)}// 打印该交易的交易哈希fmt.Printf("tx semt: %s\n", tx.Hash().Hex())// 打印交易后,两个账户的剩余余额fmt.Println("Balance 1:", b1)fmt.Println("Balance 2:", b2)
}

下面是结果截图,我用的是我之前测试的账户地址。
在这里插入图片描述

我们也可以去区块链浏览器上查看这笔交易。TESTNET Sepolia (ETH) Blockchain Explorer (etherscan.io)

在这里插入图片描述

知识点补充:

nonce

在以太坊中,nonce(Number used ONCE,一次性数字)是与每个发送者账户相关联的整数,用于确保交易顺序和唯一性。每个账户的 nonce 值是账户发送的交易数量加一,从零开始。这意味着每笔交易必须使用正确的 nonce ,以确保它们按正确的顺序执行且不会被重放。

具体来说:

  • Nonce 的作用:Nonce 确保在发送交易时,每笔交易都有唯一的标识符。它防止了重放攻击,因为同样的交易数据使用不同的 nonce 会被认为是不同的交易。
  • 获取 Nonce:通过调用以太坊客户端的 PendingNonceAt 方法,可以获取指定账户当前待处理的 nonce 值。这个方法返回的 nonce 是在该账户发送的交易队列中尚未被打包进块中的数量。在创建新交易时,通常会使用此 nonce 值加一作为新交易的 nonce。

例如,对于以下代码片段:

nonce, err := client.PendingNonceAt(context.Background(), a1)

这段代码会查询账户 a1 当前的待处理交易数量(即nonce),并将其赋值给 nonce 变量。

gas费

在以太坊中,gasPrice 是指愿意支付每单位 gas 的以太币数量,用于衡量交易的成本。Gas 本质上是执行智能合约或发送交易所需的计算资源。GasPrice 决定了矿工愿意为每单位 gas 支付多少以太币来处理你的交易。

具体来说:

  • GasPrice 的作用:GasPrice 影响到你的交易被矿工选择打包进区块的速度。较高的 GasPrice 意味着交易更有可能快速被矿工处理,因为矿工有动机选择收益更高的交易。
  • 获取推荐 GasPrice:以太坊客户端提供了一个方法 SuggestGasPrice,用于推荐当前网络上合理的 GasPrice。这个推荐的 GasPrice 通常是基于当前网络上最近几个区块中包含交易的 GasPrice 的中位数或平均值。

例如,对于以下代码片段:

gasPrice, err := client.SuggestGasPrice(context.Background())

这段代码会调用以太坊客户端的 SuggestGasPrice 方法来获取当前推荐的 GasPrice,并将其赋值给 gasPrice 变量。

安装使用solc和abigen

什么是 solc,什么是 abigen?

Solc 是 Solidity 编译器的命令行接口。Solidity 是一种用于编写智能合约的高级语言,solc 则是将 Solidity 代码编译成 Ethereum 虚拟机(EVM)可以执行的字节码的工具。solc 提供了将 Solidity 代码转换为 EVM 字节码的功能,这些字节码可以部署到以太坊区块链上执行。

Abigen 是一个工具,用于从 Solidity 合约 ABI 文件生成 Go 语言绑定代码。ABI(Application Binary Interface)文件定义了合约与外部世界的接口规范,包括合约的方法、参数和返回值类型等信息。Abigen 接收 ABI 文件作为输入,并生成相应的 Go 语言代码,这些代码可以用于与 Solidity 合约进行交互,方便在 Go 语言中调用和操作以太坊智能合约。

solc下载:

Release Version 0.8.26 · ethereum/solidity (github.com)

找到所需要的系统版本下载安装就可以了,这里就以windows举例。

在这里插入图片描述

下载后,将 solc-windows.exe 改名为 solc.exe,没有为什么,只是为了输入命令方便。

然后将其放入一个已经配置在系统环境变量中的路径下,这一点很重要,这样无论在哪个路径下都可以使用 solc 命令了。

abigen下载:

如果你已经执行过下面的命令,没执行过,那就是前面的代码没有验证,只要跑过前面的代码,这个包都是已经拉过的。

go get github.com/ethereum/go-ethereum

那么请打开你的 cmd,输入 go env,找到 GOMODCACHE 路径,打开它,找到 github.com\ethereum 下的名称为 go-ethereum 的文件夹,可能会为 go-ethereum@版本号。

一般就在 %UserProfile%\go\pkg\mod\github.com\ethereum 下面

在这里插入图片描述

在这里插入图片描述

然后打开 cmd,切换进 go-ethereum目录,然后输入以下命令。

go run build/ci.go install ./cmd/abigen

这样我们就可以在 go-ethereum/build/bin 下找到 abigen.exe 了。

在这里插入图片描述

然后将其放入一个已经配置在系统环境变量中的路径下,这一点很重要,这样无论在哪个路径下都可以使用 abigen 命令了。

补充:

这里我就随便创建了一个 D:/cmd 的文件夹,然后把 solc.exe 和 abigen.exe 放进去,然后在系统环境变量中配置了一下这个路径。

在这里插入图片描述

在这里插入图片描述

生成bin和abi文件

首先,随便写一个 todo.sol 文件,放在 contract 文件夹中。

代码:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;contract Todo{address owner;Task[] tasks;struct Task{string content;bool status;}constructor(){owner = msg.sender;}modifier isOwner(){require(owner == msg.sender);_;}function add(string memory _content) public isOwner {tasks.push(Task(_content,false));}function get(uint _id) public isOwner view returns (Task memory) {return tasks[_id];}function list() public isOwner view returns (Task[] memory){return tasks;}function update(uint _id, string memory _content) public isOwner {tasks[_id].content = _content;}function remove(uint _id) public isOwner {for(uint i = _id; i<tasks.length -1; i++){tasks[i] = tasks[i+1];}tasks.pop();}
}

然后打开终端,输入:

solc --bin --abi contract/todo.sol -o build

在这里插入图片描述

这样,我们就可以在 build 文件夹下,找到我们生成的 abi 和 bin 文件。

补充:

goland 安装 solidity 插件,在 settings->Plugins,实际上没有啥用,就是图一个好看,真正编写 solidity 还是得看 remix。

在这里插入图片描述

生成go文件

我们现在有了 abi,bin 文件,也有了abigen工具,接下来我们就可以生成相应的 go 文件了。

先创建一个 gen 文件夹。

打开命令行,输入:

abigen -bin build/Todo.bin -abi build/Todo.abi -pkg todo -out gen/todo.go

在这里插入图片描述

有了这个go文件,我们就可以调用和操作以太坊智能合约了。

使用golang在测试网上部署智能合约

接下来,我们使用之前创建的账户去调用 todo.DeployTodo() 函数就可以了。(需要有足够的SepoliaETH)

代码:

package mainimport ("context""fmt""github.com/ethereum/go-ethereum/accounts/abi/bind""github.com/ethereum/go-ethereum/accounts/keystore""github.com/ethereum/go-ethereum/crypto""github.com/ethereum/go-ethereum/ethclient"todo "go-ether-learn/gen""log""math/big""os"
)func main() {// 读取以太坊钱包文件b, err := os.ReadFile("./wallet/UTC--****-**-**T**-**-**.**********--****************************************")if err != nil {log.Fatal(err)}// 解密钱包文件,获取私钥key, err := keystore.DecryptKey(b, "password")if err != nil {log.Fatal(err)}// 连接以太坊节点client, err := ethclient.Dial("https://sepolia.infura.io/v3/********************************")if err != nil {log.Fatal(err)}defer client.Close()// 获取钱包地址add := crypto.PubkeyToAddress(key.PrivateKey.PublicKey)// 获取交易的nonce值nonce, err := client.PendingNonceAt(context.Background(), add)if err != nil {log.Fatal(err)}// 获取建议的gas价格gasPrice, err := client.SuggestGasPrice(context.Background())if err != nil {log.Fatal(err)}// 获取网络的chainIDchainID, err := client.NetworkID(context.Background())if err != nil {log.Fatal(err)}// 创建交易签名者auth, err := bind.NewKeyedTransactorWithChainID(key.PrivateKey, chainID)if err != nil {log.Fatal(err)}auth.GasPrice = gasPriceauth.GasLimit = uint64(3000000)auth.Nonce = big.NewInt(int64(nonce))// 部署智能合约a, tx, _, err := todo.DeployTodo(auth, client)if err != nil {log.Fatal(err)}// 打印部署结果fmt.Println("-----------------------------------")fmt.Println(a.Hex())             // 合约部署的地址fmt.Println(tx.Hash().Hex())     // 交易哈希fmt.Println("-----------------------------------")
}

接下来我们编译运行一下。(白天部署的gas费有点贵,建议晚上部署试试)

在这里插入图片描述

然后,我们可以在区块链浏览器上查看这个合约。TESTNET Sepolia (ETH) Blockchain Explorer (etherscan.io)

在这里插入图片描述

使用goalng与智能合约进行交互

最后,我们就可以使用goalng与智能合约进行交互了,因为没有多少SepoliaETH币了,就不演示了,大家可以自己尝试着交互一下。

代码:

package mainimport ("context""fmt""github.com/ethereum/go-ethereum/accounts/abi/bind""github.com/ethereum/go-ethereum/accounts/keystore""github.com/ethereum/go-ethereum/common""github.com/ethereum/go-ethereum/ethclient"todo "go-ether-learn/gen""log""os"
)func main() {// 读取以太坊钱包文件b, err := os.ReadFile("./wallet/UTC--****-**-**T**-**-**.**********--****************************************")if err != nil {log.Fatal(err)}// 解密钱包文件,获取私钥key, err := keystore.DecryptKey(b, "password")if err != nil {log.Fatal(err)}// 连接以太坊节点client, err := ethclient.Dial("https://sepolia.infura.io/v3/********************************")if err != nil {log.Fatal(err)}defer client.Close()// 获取当前链的 IDchainID, err := client.NetworkID(context.Background())if err != nil {log.Fatal(err)}// 获取建议的gas价格gasPrice, err := client.SuggestGasPrice(context.Background())if err != nil {log.Fatal(err)}// 转换合约地址为公共地址(合约地址为上一节部署合约的合约部署地址)cAdd := common.HexToAddress("0x****************************************")t, err := todo.NewTodo(cAdd, client)if err != nil {log.Fatal(err)}// 创建一个交易对象,设置链 ID、gas 限制和gas 价格tx, err := bind.NewKeyedTransactorWithChainID(key.PrivateKey, chainID)if err != nil {log.Fatal(err)}tx.GasLimit = 3000000tx.GasPrice = gasPrice// 调用 Todo 合约的 Add 方法tra, err := t.Add(tx, "First Task")if err != nil {log.Fatal(err)}fmt.Println(tra.Hash())// 调用 Todo 合约的 List 方法(不消耗gas)//add := crypto.PubkeyToAddress(key.PrivateKey.PublicKey)//tasks, err := t.List(&bind.CallOpts{//	From: add,//})//if err != nil {//	log.Fatal(err)//}//fmt.Println(tasks)// 调用 Todo 合约的 Update 方法//tra, err := t.Update(tx, big.NewInt(0), "update task content")//if err != nil {//	log.Fatal(err)//}//fmt.Println("Toggle tx", tra.Hash())// 调用 Todo 合约的 Remove 方法//tra, err := t.Remove(tx, big.NewInt(0))//if err != nil {//	log.Fatal(err)//}//fmt.Println("Toggle tx", tra.Hash())
}

到这里为止,你已经掌握了如何使用go去调用智能合约,与以太坊网络进行交互,可以开始尝试构建属于你的dapp了,希望这篇文章对你有所帮助。

使用golang在Etherscan上验证合约

还没造,等几天。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/370092.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RK3588 Android12实现UVC输出功能详解

首先需要在相关部分添加uvc的功能&#xff0c;这里参考一下&#xff1a;rockchip rk3588添加uvc及uvc,adb的复合设备_uvc.gs6-CSDN博客 setprop sys.usb.config none;setprop sys.usb.config uvc 或者setprop sys.usb.config none;setprop sys.usb.config uvc,adb 使rk3588 进…

一款强大且免费开源的多连接数据库管理工具

大家好&#xff0c;今天给大家分享一款免费开源的跨平台数据库管理工具DbGate。 DbGate是一款免费开源的跨平台数据库管理工具&#xff0c;支持多种数据库&#xff0c;包括MySQL、PostgreSQL、SQL Server、MongoDB、SQLite等。它可以在Windows、Linux、Mac操作系统上运行&#…

【HTML入门】第二课 - head标签下的常见表情们

目录 1 本节概要 2 head下的常见标签 2.1 网页编码设置 2.2 网页的标题 2.3 样式标签 3 head标签的内容不会显示到网页上 4 查看网页源代码 1 本节概要 上一节&#xff0c;我们说了HTML网页最基本的框架标签&#xff0c;说到标签分为head头部和body身体部分。这一小节呢…

架构师学习理解和总结

1.架构设计理念 2.架构方法论 2.1需求分析 2.1.1常见需求层次 2.1.2 常见需求结果 2.1.3 需求与架构关系 2.2 领域分析 2.3 关键需求 2.4 概念架构设计 2.5 细化架构设计 2.6 架构设计验证 3.架构设计工具 3.1 DDD领域建模 3.2 41视图分析法 3.3 UML设计工具 4.架构师知…

全能PDF工具集 -- PDF Shaper Professional v14.3 特别版

软件简介 PDF Shaper是一款功能强大的PDF工具集&#xff0c;它提供了一系列用于处理PDF文档的工具。这款软件使用户能够轻松地转换、分割、合并、提取页面以及旋转和加密PDF文件。PDF Shaper的界面简洁直观&#xff0c;使得即使是新手用户也能快速上手。它支持广泛的功能&…

Linux系统(CentOS)安装Mysql5.7.x

安装准备&#xff1a; Linux系统(CentOS)添加防火墙、iptables的安装和配置 请访问地址&#xff1a;https://blog.csdn.net/esqabc/article/details/140209894 1&#xff0c;下载mysql安装文件&#xff08;mysql-5.7.44为例&#xff09; 选择Linux通用版本64位&#xff08;L…

hdu物联网硬件实验1 小灯闪烁

物联网硬件基础实验报告 学院 班级 学号 姓名 日期 成绩 实验题目 配置环境小灯 实验目的 配置环境以及小灯闪烁 硬件原理 无 关键代码及注释 /* Blink The basic Energia example. Turns on an LED on for one second, then off for one sec…

网络安全领域国标分类汇总大全V1.0版:共计425份标准文档,全部可免费下载

《网络安全法》、《数据安全法》、《个人信息保护法》落地实施需要大量国家标准的支撑&#xff0c;博主耗时三周时间&#xff0c;吐血整理了从1999年至今相关的所有涉及安全的国家标准&#xff0c;梳理出《网络安全领域国标分类汇总大全V1.0版》&#xff0c;共计 425 项现行标准…

Cartographer前后端梳理

0. 简介 最近在研究整个SLAM框架的改进处&#xff0c;想着能不能从Cartographer中找到一些亮点可以用于参考。所以这一篇博客希望能够梳理好Cartographer前后端优化&#xff0c;并从中得到一些启发。carto整体是graph-based框架&#xff0c;前端是scan-map匹配&#xff0c;后端…

【笔记】记一次在linux上通过在线安装mysql报错 CentOS 7 的官方镜像已经不再可用的解决方法+mysql配置

报错&#xff08;恨恨恨恨恨恨恨&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff09;&#xff1a; [rootlocalhost ~]# sudo yum install mysql-server 已加载插件&#xff1a;fastestmirror, langpacks Determining fastest mirrors Could not retrie…

JMeter--定时执行的方法

原文网址&#xff1a;JMeter--定时执行的方法_IT利刃出鞘的博客-CSDN博客 简介 本文介绍JMeter如何使用定时器定时执行测试任务。 Java技术星球&#xff1a;way2j.com 方法 第一步&#xff1a;新建定时器 右键测试任务> Add > Timer> Constant Timer 如下图所示…

NTP协议格式解析

1. NTP时间戳格式 SNTP使用在RFC 1305 及其以前的版本所描述标准NTP时间戳的格式。与因特网标准标准一致&#xff0c; NTP 数据被指定为整数或定点小数&#xff0c;位以big-endian风格从左边0位或者高位计数。除非不这样指定&#xff0c;全部数量都将设成unsigned的类型&#…

加盖骑缝章软件、可以给PDF软件加盖自己的骑缝章

加盖骑缝章的软件多种多样&#xff0c;尤其是针对PDF文件&#xff0c;有多种软件可以实现给PDF文件加盖自己的骑缝章。以下是一些常用的软件及其特点&#xff1a; 1. Adobe Acrobat Pro DC 特点&#xff1a; 多功能PDF编辑&#xff1a;Adobe Acrobat Pro DC是一款功能强大的…

【Kubernetes】Pod 资源调度之亲和性调度

Pod 资源调度之亲和性调度 1.Node 亲和性调度1.1 Node 硬亲和性1.2 Node 软亲和性 2.Pod 亲和性调度2.1 Pod 硬亲和2.2 Pod 软亲和2.3 Pod 反亲和 Kubernetes 的 默认调度器 以 预选、优选、选定机制 完成将每个新的 Pod 资源绑定至为其选出的目标节点上&#xff0c;不过&#…

记录第一次写脚本

使用csh语言&#xff0c;Linux系统操作的 写和执行csh&#xff08;C Shell&#xff09;脚本不需要额外的软件&#xff0c;只需要一个支持csh的终端环境。 1.检查是否安装了C Shell 在终端terminal运行以下命令 which csh 如果返回路径&#xff0c;比如/bin/csh&#xff0c…

HTML【详解】表格 table 标签(table的属性,语义化表格,简易表格,合并单元格)

html 中的表格 <table> 由行 <tr> 组成&#xff0c;每行由单元格 <td> 组成。 所以表格是由行组成&#xff08;行由列组成&#xff09;&#xff0c;而不是由行和列组成。 table 标签 display: table &#xff0c;属于块级元素。 table 的属性 border&#…

如何用Python向PPT中批量插入图片

办公自动化办公中&#xff0c;Python最大的优势是可以批量操作&#xff0c;省去了用户粘贴、复制、插入等繁琐的操作。经常做PPT的朋友都知道&#xff0c;把图片插入到PPT当中的固定位置是一个非常繁琐的操作&#xff0c;往往调整图片时耗费大量的时间和精力。如何能省时省力插…

视频编辑和视频剪辑有什么区别 视频编辑怎么旋转方向 会声会影视频制作教程下载 视频剪辑软件免费下载中文版 视频剪辑用哪个软件

如果你还分不清视频编辑与视频剪辑&#xff0c;请务必仔细阅读本文&#xff0c;了解二者之间的不同。本文还将重点介绍&#xff0c;旋转视频方向的三种常用方法&#xff0c;手把手地教你如何旋转视频方向。有关视频编辑和视频剪辑有什么区别&#xff0c;视频编辑怎么旋转方向的…

CurrentHashMap巧妙利用位运算获取数组指定下标元素

先来了解一下数组对象在堆中的存储形式【数组长度&#xff0c;数组元素类型信息等】 【存放元素对象的空间】 Ma 基础信息实例数据内存填充Mark Word,ClassPointer,数组长度第一个元素第二个元素固定的填充内容 所以我们想要获取某个下标的元素首先要获取这个元素的起始位置…

CSS实现图片裁剪居中(只截取剪裁图片中间部分,图片不变形)

1.第一种方式&#xff1a;&#xff08;直接给图片设置&#xff1a;object-fit:cover;&#xff09; .imgbox{width: 100%;height:200px;overflow: hidden;position: relative;img{width: 100%;height: 100%; //图片要设置高度display: block;position: absolute;left: 0;right…