Skip to content

Instantly share code, notes, and snippets.

@focusj
Last active March 24, 2022 01:37
Show Gist options
  • Save focusj/58cbc3ab680a1297284843af96e9ffc5 to your computer and use it in GitHub Desktop.
Save focusj/58cbc3ab680a1297284843af96e9ffc5 to your computer and use it in GitHub Desktop.
etherscan api wrapper
package main
import (
"encoding/json"
"errors"
"fmt"
"strconv"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/go-resty/resty/v2"
"github.com/inconshreveable/log15"
)
var logger = log15.New("module", "networking")
type Etherscan struct {
client *resty.Client
host string
apiKey string
}
func NewEtherscan(client *resty.Client, host string, apiKey string) *Etherscan {
return &Etherscan{client, host, apiKey}
}
type Response[R any] struct {
Status string
Message string
Result R
}
func doGetRequest[R, T any](client *resty.Client, host string, params map[string]string, bodyParser func(body R) (T, error)) (t T, err error) {
resp, err := client.R().SetResult(Response[R]{}).SetQueryParams(params).EnableTrace().Get(host)
if err != nil {
logger.Error("doGet failed when http call", "host", host, "params", params, "err", err)
return t, err
}
result := resp.Result().(*Response[R])
if result.Status == "0" {
return t, errors.New(result.Message)
}
return bodyParser(result.Result)
}
func getEventLogsParser(result []map[string]interface{}) ([]types.Log, error) {
var eventLogs []types.Log
for _, log := range result {
var topics []common.Hash
for _, topic := range log["topics"].([]interface{}) {
topics = append(topics, common.HexToHash(topic.(string)))
}
data, _ := hexutil.Decode(log["data"].(string))
blockNumber, _ := hexutil.DecodeUint64(log["blockNumber"].(string))
txIndex, _ := hexutil.DecodeUint64(log["transactionIndex"].(string))
var eventLog = types.Log{}
eventLog.Address = common.HexToAddress(log["address"].(string))
eventLog.Topics = topics
eventLog.Data = data
eventLog.BlockNumber = blockNumber
eventLog.TxHash = common.HexToHash(log["transactionHash"].(string))
eventLog.TxIndex = uint(txIndex)
if blockHash, ok := log["blockHash"]; ok {
eventLog.BlockHash = common.HexToHash(blockHash.(string))
}
if indexStr, ok := log["index"]; ok {
index, _ := hexutil.DecodeUint64(indexStr.(string))
eventLog.Index = uint(index)
}
if removed, ok := log["removed"]; ok {
eventLog.Removed = removed.(bool)
}
eventLogs = append(eventLogs, eventLog)
}
return eventLogs, nil
}
// GetEventLogs
// endBlock: when endBlock is 0, it will be set 'latest'
func (e *Etherscan) GetEventLogs(contract string, topic0 string, fromBlock, endBlock uint64) ([]types.Log, error) {
fromBlockStr := strconv.FormatUint(fromBlock, 10)
endBlockStr := "latest"
if endBlock > 0 {
endBlockStr = strconv.FormatUint(endBlock, 10)
}
params := make(map[string]string)
params["module"] = "logs"
params["action"] = "getLogs"
params["fromBlock"] = fromBlockStr
params["toBlock"] = endBlockStr
params["address"] = contract
params["topic0"] = topic0
params["apikey"] = e.apiKey
return doGetRequest(e.client, e.host, params, getEventLogsParser)
}
func (e *Etherscan) GetLatestBlock() (uint64, error) {
params := make(map[string]string)
params["module"] = "proxy"
params["action"] = "eth_blockNumber"
params["apikey"] = e.apiKey
return doGetRequest(e.client, e.host, params, func(body string) (uint64, error) {
return hexutil.DecodeUint64(body)
})
}
func (e *Etherscan) GetBlockTimestamp(blockNumber uint64) (uint64, error) {
params := make(map[string]string)
params["module"] = "block"
params["action"] = "getblockreward"
params["blockno"] = strconv.FormatInt(int64(blockNumber), 10)
params["apikey"] = e.apiKey
return doGetRequest(e.client, e.host, params, func(body struct {
TimeStamp string `json:"timeStamp"`
}) (uint64, error) {
return strconv.ParseUint(body.TimeStamp, 10, 64)
})
}
func main() {
etherscan := NewEtherscan(resty.New(), "https://api-testnet.arbiscan.io/api", "XZVIT6EF33QDGSED7S9YHC7UJ218PDKB82")
logs, err := etherscan.GetEventLogs("0x01D9C1fB595fe91364771aee12e1E7188B1B83CD", "0x1e270fe7f6f066c8453a91b522924a5a45c7c3bebf3901d91b726267b15b66d3", uint64(7301447), 0)
if err != nil {
panic(err)
}
fmt.Println(logs)
blockNo, err := etherscan.GetLatestBlock()
if err != nil {
panic(err)
}
fmt.Println(blockNo)
timestamp, err := etherscan.GetBlockTimestamp(blockNo)
if err != nil {
panic(err)
}
fmt.Println(timestamp)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment