go 调用solidity

49 阅读2分钟

在truffle框架中 生成了student_storage.go
调用 这个文件 如下:


package admin

import (
    "context"
    "fmt"
    "github.com/ethereum/go-ethereum/core/types"
    "log"
    "math/big"

    "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"
)

// StudentService 提供与 StudentStorage 合约交互的服务
type StudentService struct {
    client *ethclient.Client
}

// NewStudentService 创建一个新的 StudentService 实例
func NewStudentService(client *ethclient.Client) *StudentService {
    return &StudentService{
       client: client,
    }
}

// ConnectEthNode 连接到以太坊节点
func ConnectEthNode(nodeURL string) (*ethclient.Client, error) {
    client, err := ethclient.Dial(nodeURL)
    if err != nil {
       return nil, fmt.Errorf("无法连接到以太坊节点: %v", err)
    }
    return client, nil
}

// LoadContract 加载 StudentStorage 合约实例
func (s *StudentService) LoadContract(contractAddress string) (*StudentStorage, error) {
    addr := common.HexToAddress(contractAddress)

    instance, err := NewStudentStorage(addr, s.client)
    if err != nil {
       return nil, fmt.Errorf("无法实例化 StudentStorage 合约: %v", err)
    }

    return instance, nil
}

// PrepareAuth 准备交易授权
func (s *StudentService) PrepareAuth(privateKeyStr string) (*bind.TransactOpts, error) {
    // 解析私钥
    privateKey, err := crypto.HexToECDSA(privateKeyStr)
    if err != nil {
       return nil, fmt.Errorf("无法解析私钥: %v", err)
    }

    // 创建交易授权
    auth := bind.NewKeyedTransactor(privateKey)

    // 设置 Gas 价格和限制
    gasPrice, err := s.client.SuggestGasPrice(context.Background())
    if err != nil {
       return nil, fmt.Errorf("无法建议 Gas 价格: %v", err)
    }
    auth.GasPrice = gasPrice
    auth.GasLimit = uint64(300000) // 设置足够的 Gas 限制

    // 设置交易发送方地址
    auth.From = crypto.PubkeyToAddress(privateKey.PublicKey)

    return auth, nil
}

// SetStudentData 调用合约的 SetData 方法设置学生数据
func (s *StudentService) SetStudentData(contract *StudentStorage, auth *bind.TransactOpts, name string, age *big.Int) (*types.Transaction, error) {
    tx, err := contract.SetData(auth, name, age)
    if err != nil {
       return nil, fmt.Errorf("调用 SetData 方法失败: %v", err)
    }
    return tx, nil
}

// 示例使用函数
func ExampleSetData() {
    // 1. 连接以太坊节点
    client, err := ConnectEthNode("http://localhost:7545")
    if err != nil {
       log.Fatalf("连接以太坊节点失败: %v", err)
    }
    defer client.Close()

    // 2. 创建服务实例
    service := NewStudentService(client)

    // 3. 加载合约实例
    contractAddress := "0x14F648Cd6Ab7c069106316DDb72b7e3e2E3040B1" // 替换为实际合约地址
    contract, err := service.LoadContract(contractAddress)
    if err != nil {
       log.Fatalf("加载合约失败: %v", err)
    }

    // 4. 准备交易授权
    privateKey := "87ceadb25ffad3daefb5fafe101ba4d49c328000843e76062d7d5230ac3bbf8c" // 替换为实际私钥
    auth, err := service.PrepareAuth(privateKey)
    if err != nil {
       log.Fatalf("准备交易授权失败: %v", err)
    }

    // 5. 调用 SetData 方法
    name := "张三"
    age := big.NewInt(22)
    tx, err := service.SetStudentData(contract, auth, name, age)
    if err != nil {
       log.Fatalf("设置学生数据失败: %v", err)
    }

    fmt.Printf("交易已发送: %s\n", tx.Hash().Hex())

    log.Printf("执行成功。。。。。")
}


在项目里调用了接口

image.png

image.png

查看交易 在Ganache

image.png