Как получить доступ к журналу событий, зная адрес контракта (golang)?

На данный момент я разрабатываю dapps, которые используют смарт-контракты в качестве хранилища для конкретных данных. Я использую abigen для создания конкретной привязки к моему контракту. Если кто-то попытается изменить состояние контракта, я использую событие для регистрации этого действия. Но я застрял, потому что я действительно не понимаю, как я могу просмотреть историю журнала определенного события, используя go ethereum.

Как я могу использовать вызов eth_getlogsметода json rpc и получить все журналы, которые хранятся на этом адресе контракта, с помощью go?

Я буду признателен за фрагмент кода.

Заранее спасибо!

Ответы (2)

Обычно вы сначала создаете новый фильтр ( eth_newFilter+ eth_getFilterLogs) и повторно используете этот фильтр для многократного выполнения одного и того же запроса, а также для прослушивания изменений. Однако вы также можете установить специальный фильтр с помощью eth_getLogsссылки на темы, по которым вы хотите выполнить поиск.

Тема — это фрагмент данных, который вы ищете. Например, если у вас есть следующее событие:

Transfer(address to, address from)

Следующий фильтр будет искать все журналы, идущие в 0xb3904758c0d3bfc25746c47caa45b01da8930e19:

[0x000000000000000000000000b3904758c0d3bfc25746c47caa45b01da8930e19, null]

Этот фильтр будет искать все журналы, поступающие из 0xb3904758c0d3bfc25746c47caa45b01da8930e19:

[null, 0x000000000000000000000000b3904758c0d3bfc25746c47caa45b01da8930e19]

И этот фильтр будет искать все журналы, идущие 0xb3904758c0d3bfc25746c47caa45b01da8930e19от 0x8cc19c7b50857abbfbeeed31c302319a075d4a9b:

[0x000000000000000000000000b3904758c0d3bfc25746c47caa45b01da8930e19, 0x0000000000000000000000008cc19c7b50857abbfbeeed31c302319a075d4a9b

Полная оболочка golang для RPC-запросов будет выглядеть примерно так:

// This needs to be instantiated
type EthereumClient struct {
  URL string
}

// Basic RPC repsonse format
type JSONRPCRequest struct {
  JSONRPC string        `json:"jsonrpc"`
  Method  string        `json:"method"`
  ID      int64         `json:"id"`
  Params  []interface{} `json:"params"`
}

// Base struct
type ResponseBase struct {
  JSONRPC string `json:"jsonrpc"`
  ID      int64  `json:"id"`
}

// Response struct based on below RPC methods
type Response struct {
  ResponseBase
  Result string `json:"result"`
}

// ToJSON marshals a JSONRPCRequest into JSON
func (req *JSONRPCRequest) ToJSON() ([]byte, error) {
  s, err := json.Marshal(req)
  if err != nil {
    return nil, err
  }
  return s, nil
}

// Get logs given an array of topics
func (client *EthereumClient) Eth_getLogs(topics string[]) (string, error) {
  reqBody := JSONRPCRequest{
    JSONRPC: "2.0",
    ID:      1,
    Method:  "eth_sendRawTransaction",
    Params:  []interface{}{topics},
  }
  res, err := client.issueRequest(&reqBody)
  if err != nil {
    return "", err
  }

  var clientResp Response
  err = json.Unmarshal(res, &clientResp)
  if err != nil {
    return "", err
  }
  return clientResp.Result, nil
}

Можно EthereumClientсоздать экземпляр в другом пакете примерно так:

// Global client connection
var client = EthereumClient{}

// provider = e.g. 'localhost:8545'
func ConnectToRPC(provider string) {
  client = EthereumClient{provider}
}

Теперь это clientможно использовать для запуска нового фильтра и получения журналов из этого фильтра.

У меня нет конкретного примера для этого варианта использования, но, пожалуйста, посмотрите здесь несколько примеров выполнения запросов RPC в Go.

Вы можете добавить адрес контракта в качестве параметра вызова eth_getLogs:

curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"address":["YOUR_CONTRACT_ADDRESS"]}],"id":74}'

Если вы заинтересованы в постоянном опросе обновлений событий, вы можете сначала создать фильтр с помощью eth_newFilter, а затем запрашивать обновления с помощью eth_getFilterChanges .