go+solidity+web写一个简单的水龙头项目1

517 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

1、编写智能合约

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract Faucet {

   //每天转账次数
   uint transferNum=0;

   //每次转账金额
   uint eachAmount =1 ether;

   function withdraw(address addr) payable public {

      require(transferNum < 10,"hightest transfer num");

      payable(addr).transfer(eachAmount);

      transferNum++;
   }

   // function pay() public payable {}
    fallback() payable external {}
    receive() payable external {}

}

2、与go交互,生成go文件

1、使用remix复制abi 2、控制台输入命令

//facuet为文件名称,Agreement为文件夹名称
geth abigen --abi faucet.abi --pkg Agreement --type faucet --out faucet.go

3、之后在Agreement文件夹下生成了go文件

3、调用go文件中的方法

1、初始化

//定义常量,方便迭代、更改
const (
   chainID = 8565 //8888  //链id
   //账户文件
   fileKeystore  = "UTC--2021-12-28T17-30-07.282049100Z--982ca83b2221f620b7c43303cc66a34b6c1c70ad" 
   privateKey    = "111"   //账户文件密码
   faucetAddress = "0x4215fd451f6219DA9eb9216Bcc5E74F96B55C884" //合约地址
   gasLimit      = 3000000   
)

// HaveClient 获取 ethclient.Client 对象
func HaveClient() (*ethclient.Client, error) {
   client, err := ethclient.Dial("http://localhost:9696")  //区块链节点的url
   if err != nil {
      log.Fatal(err)
   }
   defer client.Close()
   //Background()返回一个非空的Context。 通常由主函数使用
   chainID, err := client.NetworkID(context.Background()) 
      if err != nil {
         log.Fatal(err)
      }
      fmt.Println(chainID)
   return client, err
}


// HaveFacet 获取 NewFaucet
func HaveFacet(client *ethclient.Client) (*Faucet, error) {
//通过合约地址返回各种方法
   ins, err := NewFaucet(common.HexToAddress(faucetAddress), client)
   if err != nil {
      log.Fatal(err)
   }
   return ins, err
}

//获取账户文件和密码 opts
func HaveGetOpts() *bind.TransactOpts {
   //账户文件
   b, err := ioutil.ReadFile(fileKeystore)
   if err != nil {
      log.Fatal(err)
   }
   //账户密码
   key, err := keystore.DecryptKey(b, privateKey)
   if err != nil {
      log.Fatal(err)
   }
   fmt.Println("key:", key)
   reader, _ := os.Open(fileKeystore)
   //这个方法即将被弃用,所以我把它注释了,使用下面这种方法
   //opts, err := bind.NewTransactor(reader, "111") 
   opts, err := bind.NewTransactorWithChainID(reader,"111",big.NewInt(chainID))
   if err != nil {
      log.Fatal("NewTransactor ", err)
   }
   return opts
}

//获取gasPrice
func getGasPrice(client *ethclient.Client) (*big.Int, error) {
   gasPrice, err := client.SuggestGasPrice(context.Background())
   if err != nil {
      log.Fatal(err)
   }
   return gasPrice, err
}

2、调用方法

//水龙头,合约给账户发送以太币
func SendFaucetETH(client *ethclient.Client, contract *FaucetTransactor, Address common.Address) (*types.Transaction, error) {
//实例化,使用账户密码文件
   opts := HaveGetOpts()
   //通过调用faucet方法,进行转账操作
   res, err := contract.Faucet(opts, Address)
   //gasPrice, err := client.SuggestGasPrice(context.Background())
   if err != nil {
      log.Fatal(err)
   }
   opts.GasLimit = gasLimit
   opts.GasPrice, err = getGasPrice(client)
   return res, err
}