2023-03-27 12:14:12 -07:00
|
|
|
package chains
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
2024-03-19 11:47:43 -07:00
|
|
|
|
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/common/pool"
|
|
|
|
"github.com/wormhole-foundation/wormhole-explorer/txtracker/internal/metrics"
|
|
|
|
sdk "github.com/wormhole-foundation/wormhole/sdk/vaa"
|
|
|
|
"go.uber.org/zap"
|
2023-03-27 12:14:12 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
type ethGetTransactionByHashResponse struct {
|
|
|
|
BlockHash string `json:"blockHash"`
|
|
|
|
BlockNumber string `json:"blockNumber"`
|
|
|
|
From string `json:"from"`
|
|
|
|
To string `json:"to"`
|
|
|
|
}
|
|
|
|
|
2024-03-19 11:47:43 -07:00
|
|
|
type apiEvm struct {
|
|
|
|
chainId sdk.ChainID
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *apiEvm) FetchEvmTx(
|
|
|
|
ctx context.Context,
|
|
|
|
pool *pool.Pool,
|
|
|
|
txHash string,
|
|
|
|
metrics metrics.Metrics,
|
|
|
|
logger *zap.Logger,
|
|
|
|
) (*TxDetail, error) {
|
|
|
|
// get rpc sorted by score and priority.
|
|
|
|
rpcs := pool.GetItems()
|
|
|
|
if len(rpcs) == 0 {
|
|
|
|
return nil, ErrChainNotSupported
|
|
|
|
}
|
|
|
|
|
|
|
|
var txDetail *TxDetail
|
|
|
|
var err error
|
|
|
|
for _, rpc := range rpcs {
|
|
|
|
// Wait for the RPC rate limiter
|
|
|
|
rpc.Wait(ctx)
|
|
|
|
txDetail, err = e.fetchEvmTx(ctx, rpc.Id, txHash)
|
|
|
|
if err != nil {
|
|
|
|
metrics.IncCallRpcError(uint16(e.chainId), rpc.Description)
|
|
|
|
logger.Debug("Failed to fetch transaction from evm node", zap.String("url", rpc.Id), zap.Error(err))
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
metrics.IncCallRpcSuccess(uint16(e.chainId), rpc.Description)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
return txDetail, err
|
2023-03-27 12:14:12 -07:00
|
|
|
}
|
|
|
|
|
2024-03-19 11:47:43 -07:00
|
|
|
func (e *apiEvm) fetchEvmTx(
|
2023-03-27 12:14:12 -07:00
|
|
|
ctx context.Context,
|
2023-03-30 08:25:16 -07:00
|
|
|
baseUrl string,
|
2023-07-04 11:25:08 -07:00
|
|
|
txHash string,
|
2023-03-27 12:14:12 -07:00
|
|
|
) (*TxDetail, error) {
|
|
|
|
|
|
|
|
// initialize RPC client
|
2023-07-04 11:25:08 -07:00
|
|
|
client, err := rpcDialContext(ctx, baseUrl)
|
2023-03-27 12:14:12 -07:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to initialize RPC client: %w", err)
|
|
|
|
}
|
|
|
|
defer client.Close()
|
|
|
|
|
2023-11-27 07:31:35 -08:00
|
|
|
nativeTxHash := txHashLowerCaseWith0x(txHash)
|
2023-03-27 12:14:12 -07:00
|
|
|
// query transaction data
|
|
|
|
var txReply ethGetTransactionByHashResponse
|
2023-07-04 11:25:08 -07:00
|
|
|
{
|
2024-03-19 11:47:43 -07:00
|
|
|
err = client.CallContext(ctx, &txReply, "eth_getTransactionByHash", nativeTxHash)
|
2023-07-04 11:25:08 -07:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to get tx by hash: %w", err)
|
|
|
|
}
|
|
|
|
if txReply.BlockHash == "" || txReply.From == "" {
|
|
|
|
return nil, ErrTransactionNotFound
|
|
|
|
}
|
2023-04-05 06:33:28 -07:00
|
|
|
}
|
2023-03-27 12:14:12 -07:00
|
|
|
|
|
|
|
// build results and return
|
|
|
|
txDetail := &TxDetail{
|
2023-06-14 13:46:53 -07:00
|
|
|
From: strings.ToLower(txReply.From),
|
2023-11-27 07:31:35 -08:00
|
|
|
NativeTxHash: nativeTxHash,
|
2023-03-27 12:14:12 -07:00
|
|
|
}
|
|
|
|
return txDetail, nil
|
|
|
|
}
|