Golang监听solidity事件
合约
此合约的作用是贡献0.1USDT后成为内测用户。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| // SPDX-License-Identifier: MIT pragma solidity 0.7.6;
import "./IBEP20.sol";
contract InternalTest{ IBEP20 private BSCUSDT; mapping (address => bool) public InternalTestUser; uint256 public constant InternalTestPirce = 1 * 1e17; address public owner; event BeInternalTestUser(address to);
constructor(address tokenAddress) { BSCUSDT = IBEP20(tokenAddress); owner = msg.sender; }
function beInternalTestUser() payable external{ BSCUSDT.transferFrom(msg.sender,owner,InternalTestPirce); require(!InternalTestUser[msg.sender],"already an internal test user"); InternalTestUser[msg.sender] = true; emit BeInternalTestUser(msg.sender); } }
|
生成Go文件
1
| abigen --sol=./contracts/InternalTest.sol --pkg=InternalTest --out=./contracts/InternalTest.go
|
生成名为InternalTest的go文件
socket地址获取:https://account.getblock.io/
监听实现(网上教程方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| package main
import ( InternalTest "awesomeProject/contracts" "context" "fmt" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "log" "strings" )
func main() { client, err := ethclient.Dial("wss://bsc.getblock.io/testnet/?api_key=022c82c1-6769-4a1c-b5f4-6e1d46b90826") if err != nil { log.Fatal(err) }
contractAddress := common.HexToAddress("0x9411FE301d860D4a9b196d9132cDC5841bB12e63")
query := ethereum.FilterQuery{ Addresses: []common.Address{contractAddress}, }
logs := make(chan types.Log) sub, err := client.SubscribeFilterLogs(context.Background(), query, logs) if err != nil { log.Fatal(err) }
for { select { case err := <-sub.Err(): log.Fatal(err) case vLog := <-logs: contractAbi, err := abi.JSON(strings.NewReader(InternalTest.InternalTestABI)) if err != nil{ fmt.Println(1,err) } unpack, err := contractAbi.Unpack("BeInternalTestUser", vLog.Data) if err != nil { fmt.Println(2,err) } fmt.Println(unpack) } } }
|
这个方案是按照网上的一些教程编写而成,通过实验我发现,contractAbi.Unpack("BeInternalTestUser", vLog.Data)
这个方法并没有过滤到指定事件,而是监听了所有事件,这远远违背了我们的初衷,通过abigen生成的代码我们可以看到获取指定事件的监听方法。
监听实现(实际实现方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| func StartSubscribe() { client, err := ethclient.Dial("wss://bsc.getblock.io/testnet/?api_key=022c82c1-6769-4a1c-b5f4-6e1d46b90826") if err != nil { log.Fatal(err) } defer func() { if err := recover();err != nil{ client.Close() StartSubscribe() } }()
contractAddress := common.HexToAddress("0x9411FE301d860D4a9b196d9132cDC5841bB12e63") newInternalTest , _ := InternalTest.NewInternalTest(contractAddress,client) logs := make(chan *InternalTest.InternalTestBeInternalTestUser) sub, err := newInternalTest.WatchBeInternalTestUser(nil,logs) if err != nil { log.Fatal(err) } for { select { case err := <-sub.Err(): log.Panic(err) case vLog := <-logs: fmt.Println(vLog.To) } } }
|
首先链接到区块链socket,并通过合约地址实例化合约,调用WatchBeInternalTestUser
方法就可以监听到BeInternalTestUser
这个事件了,我在合约种又加入了几种事件,通过实验表明此种方法只会监听到一种事件。