wormhole-explorer/tx-tracker/chains/eth.go

78 lines
1.8 KiB
Go

package chains
import (
"context"
"fmt"
"strings"
"github.com/ethereum/go-ethereum/rpc"
)
type ethGetTransactionByHashResponse struct {
BlockHash string `json:"blockHash"`
BlockNumber string `json:"blockNumber"`
From string `json:"from"`
To string `json:"to"`
}
type ethGetBlockByHashResponse struct {
Timestamp string `json:"timestamp"`
Number string `json:"number"`
}
func fetchEthTx(
ctx context.Context,
txHash string,
baseUrl string,
apiKey string,
) (*TxDetail, error) {
// build RPC URL
url := baseUrl
if apiKey != "" {
url += "/" + apiKey
}
// initialize RPC client
client, err := rpc.DialContext(ctx, url)
if err != nil {
return nil, fmt.Errorf("failed to initialize RPC client: %w", err)
}
defer client.Close()
// query transaction data
var txReply ethGetTransactionByHashResponse
err = client.CallContext(ctx, &txReply, "eth_getTransactionByHash", "0x"+txHash)
if err != nil {
return nil, fmt.Errorf("failed to get tx by hash: %w", err)
}
if txReply.BlockHash == "" || txReply.From == "" {
return nil, ErrTransactionNotFound
}
// query block data
blkParams := []interface{}{
txReply.BlockHash, // tx hash
false, // include transactions?
}
var blkReply ethGetBlockByHashResponse
err = client.CallContext(ctx, &blkReply, "eth_getBlockByHash", blkParams...)
if err != nil {
return nil, fmt.Errorf("failed to get block by hash: %w", err)
}
// parse transaction timestamp
timestamp, err := timestampFromHex(blkReply.Timestamp)
if err != nil {
return nil, fmt.Errorf("failed to parse block timestamp: %w", err)
}
// build results and return
txDetail := &TxDetail{
Signer: strings.ToLower(txReply.From),
Timestamp: timestamp,
NativeTxHash: fmt.Sprintf("0x%s", strings.ToLower(txHash)),
}
return txDetail, nil
}