Dans l'article précédent, nous avons expliqué comment go utilise les sélecteurs de fonction pour appeler des contrats intelligents. Ensuite, apprenons à utiliser abi pour appeler des contrats intelligents.
Cours de cette série :
Section 1 : Appel du sélecteur de fonction pour interagir avec les contrats intelligents à l'aide de go
Section 2 : Appel Abi utilisant go pour interagir avec les contrats intelligents
1. Tout d'abord, installons go-ethereum
go get -u github.com/ethereum/go-ethereum
2. Créez un nouveau fichier main.go et ajoutez des dépendances
import (
"context"
"crypto/ecdsa"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"math/big"
"os"
)
3. Définir des constantes
const (
privateKey = "你的钱包私钥"
contractAddress = "调用合约地址"
toAddress = "接收转账地址" //这里我使用transfer方法作为案例,所以需要一个接收转账地址
)
4. Définir la fonction appelante
func transfer(client *ethclient.Client, privateKey, toAddress, contract string) (string, error) {}
4.1. Déduire d'abord la clé publique de la clé privée, puis déduire l'adresse du portefeuille de la clé publique
//从私钥推导出 公钥
privateKeyECDSA, err := crypto.HexToECDSA(privateKey)
if err != nil {
fmt.Println("crypto.HexToECDSA error ,", err)
return "", err
}
publicKey := privateKeyECDSA.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
fmt.Println("publicKeyECDSA error ,", err)
return "", err
}
//从公钥推导出钱包地址
fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
fmt.Println("钱包地址:", fromAddress.Hex())
4.2 Construire les paramètres de requête
Ceci est différent de la manière d'utiliser les sélecteurs de fonction, qui est également au centre de cet article
4.2.1. Préparer le fichier abi abi.json du contrat
( Si vous n'obtenez pas le fichier abi du contrat, vous pouvez suivre le compte officiel : Wai Bai San Preacher ( web3_preacher ) et me laisser un message )
[
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
.....
]
4.2.2, lire le fichier abi
//读取abi文件
abiData, err := os.ReadFile("./part2/abi.json")
if err != nil {
fmt.Println("os.ReadFile error ,", err)
return "", err
}
4.2.3. Convertir les données abi en objets abi contractuels
contractAbi, err := abi.JSON(bytes.NewReader(abiData))
if err != nil {
fmt.Println("abi.JSON error ,", err)
return "", err
}
4.2.4. L'objet contract abi regroupe les méthodes et les paramètres à appeler
amount, _ := new(big.Int).SetString("100000000000000000000", 10)
data, err := contractAbi.Pack("transfer", common.HexToAddress(toAddress), amount)
if err != nil {
fmt.Println("contractAbi.Pack error ,", err)
return "", err
}
En fait, cette opération est la même que le code que nous avons évoqué dans le premier chapitre (voir ci-dessous) Si cela vous intéresse, vous pouvez lire vous-même le code source de la méthode contractAbi.Pack .
var data []byte
methodName := crypto.Keccak256([]byte("transfer(address,uint256)"))[:4]
paddedToAddress := common.LeftPadBytes(common.HexToAddress(toAddress).Bytes(), 32)
amount, _ := new(big.Int).SetString("100000000000000000000", 10)
paddedAmount := common.LeftPadBytes(amount.Bytes(), 32)
data = append(data, methodName...)
data = append(data, paddedToAddress...)
data = append(data, paddedAmount...)
4.3 Construire des objets de transaction
//获取nonce
nonce, err := client.NonceAt(context.Background(), fromAddress, nil)
if err != nil {
return "", err
}
//获取小费
gasTipCap, _ := client.SuggestGasTipCap(context.Background())
//transfer 默认是 使用 21000 gas
gas := uint64(100000)
//最大gas fee
gasFeeCap := big.NewInt(38694000460)
contractAddress := common.HexToAddress(contract)
//创建交易
tx := types.NewTx(&types.DynamicFeeTx{
Nonce: nonce,
GasTipCap: gasTipCap,
GasFeeCap: gasFeeCap,
Gas: gas,
To: &contractAddress,
Value: big.NewInt(0),
Data: data,
})
4.4. Signature de la transaction/transmission de la transaction
// 获取当前区块链的ChainID
chainID, err := client.ChainID(context.Background())
if err != nil {
fmt.Println("获取ChainID失败:", err)
return "", err
}
fmt.Println("当前区块链的ChainID:", chainID)
//创建签名者
signer := types.NewLondonSigner(chainID)
//对交易进行签名
signTx, err := types.SignTx(tx, signer, privateKeyECDSA)
if err != nil {
return "", err
}
//发送交易
err = client.SendTransaction(context.Background(), signTx)
if err != nil {
return "", err
}
4.5, appelez la fonction dans la fonction principale
func main() {
client, err := ethclient.Dial("https://goerli.infura.io/v3/3214cac49d354e48ad196cdfcefae1f8")
if err != nil {
fmt.Println("ethclient.Dial error : ", err)
os.Exit(0)
}
tx, err := transfer(client, privateKey, toAddress, contractAddress)
if err != nil {
fmt.Println("transfer error : ", err)
os.Exit(0)
}
fmt.Println("使用go调用智能合约第二讲:transfer tx : ", tx)
}
5. Exécutez la méthode principale
Notre code a été exécuté avec succès, allons dans l'explorateur de blockchain pour jeter un œil
On peut voir que la blockchain a confirmé notre transaction
Dans ce tutoriel, nous avons appris à utiliser go to call contract abi pour interagir avec les contrats intelligents. Si vous avez des questions pendant le processus d'apprentissage, vous pouvez me laisser un message sur le compte officiel. Je vous répondrai dès que je verrai De plus, le compte officiel partagera également de temps en temps des informations de pointe sur la blockchain et le Web3. Les amis intéressés peuvent rester à l'écoute
Veuillez faire attention au compte officiel : Web3_preacher ( web3_preacher ) , répondez "go contract call" pour recevoir le code complet