2023-07-04 11:25:08 -07:00
|
|
|
package chains
|
|
|
|
|
|
|
|
import (
|
2023-09-04 11:17:23 -07:00
|
|
|
"bytes"
|
2023-07-04 11:25:08 -07:00
|
|
|
"context"
|
2023-09-04 11:17:23 -07:00
|
|
|
"encoding/json"
|
2023-07-04 11:25:08 -07:00
|
|
|
"fmt"
|
2023-09-04 11:17:23 -07:00
|
|
|
"io"
|
2023-07-04 11:25:08 -07:00
|
|
|
"net/http"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/rpc"
|
2024-03-19 11:47:43 -07:00
|
|
|
sdk "github.com/wormhole-foundation/wormhole/sdk/vaa"
|
2023-07-04 11:25:08 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
// httpGet is a helper function that performs an HTTP request.
|
2024-03-19 11:47:43 -07:00
|
|
|
func httpGet(ctx context.Context, url string) ([]byte, error) {
|
2023-07-04 11:25:08 -07:00
|
|
|
|
|
|
|
// Build the HTTP request
|
|
|
|
request, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to create request: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send it
|
|
|
|
var client http.Client
|
|
|
|
response, err := client.Do(request)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to query url: %w", err)
|
|
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
|
|
return nil, fmt.Errorf("unexpected HTTP status code: %d", response.StatusCode)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the response body and return
|
2023-09-04 11:17:23 -07:00
|
|
|
body, err := io.ReadAll(response.Body)
|
2023-07-04 11:25:08 -07:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to read response body: %w", err)
|
|
|
|
}
|
|
|
|
return body, nil
|
|
|
|
}
|
|
|
|
|
2023-09-04 11:17:23 -07:00
|
|
|
// httpPost is a helper function that performs an HTTP request.
|
2024-03-19 11:47:43 -07:00
|
|
|
// func httpPost(ctx context.Context, rateLimiter *time.Ticker, url string, body any) ([]byte, error) {
|
|
|
|
func httpPost(ctx context.Context, url string, body any) ([]byte, error) {
|
2023-09-04 11:17:23 -07:00
|
|
|
|
|
|
|
b, err := json.Marshal(body)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build the HTTP request
|
|
|
|
request, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(b))
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to create request: %w", err)
|
|
|
|
}
|
|
|
|
request.Header.Set("Content-Type", "application/json")
|
|
|
|
|
|
|
|
// Send it
|
|
|
|
var client http.Client
|
|
|
|
response, err := client.Do(request)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to query url: %w", err)
|
|
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
|
|
return nil, fmt.Errorf("unexpected HTTP status code: %d", response.StatusCode)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the response body and return
|
|
|
|
result, err := io.ReadAll(response.Body)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to read response body: %w", err)
|
|
|
|
}
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
|
2023-07-04 11:25:08 -07:00
|
|
|
type rateLimitedRpcClient struct {
|
|
|
|
client *rpc.Client
|
|
|
|
}
|
|
|
|
|
|
|
|
func rpcDialContext(ctx context.Context, url string) (*rateLimitedRpcClient, error) {
|
|
|
|
|
|
|
|
client, err := rpc.DialContext(ctx, url)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp := rateLimitedRpcClient{
|
|
|
|
client: client,
|
|
|
|
}
|
|
|
|
return &tmp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *rateLimitedRpcClient) CallContext(
|
|
|
|
ctx context.Context,
|
|
|
|
result interface{},
|
|
|
|
method string,
|
|
|
|
args ...interface{},
|
|
|
|
) error {
|
|
|
|
return c.client.CallContext(ctx, result, method, args...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *rateLimitedRpcClient) Close() {
|
|
|
|
c.client.Close()
|
|
|
|
}
|
2023-09-04 11:17:23 -07:00
|
|
|
|
|
|
|
func txHashLowerCaseWith0x(v string) string {
|
|
|
|
if strings.HasPrefix(v, "0x") {
|
|
|
|
return strings.ToLower(v)
|
|
|
|
}
|
|
|
|
return "0x" + strings.ToLower(v)
|
|
|
|
}
|
2024-03-19 11:47:43 -07:00
|
|
|
|
|
|
|
func FormatTxHashByChain(chainId sdk.ChainID, txHash string) string {
|
|
|
|
switch chainId {
|
|
|
|
case sdk.ChainIDAcala,
|
|
|
|
sdk.ChainIDArbitrum,
|
|
|
|
sdk.ChainIDArbitrumSepolia,
|
|
|
|
sdk.ChainIDAvalanche,
|
|
|
|
sdk.ChainIDBase,
|
|
|
|
sdk.ChainIDBaseSepolia,
|
|
|
|
sdk.ChainIDBSC,
|
|
|
|
sdk.ChainIDCelo,
|
|
|
|
sdk.ChainIDEthereum,
|
|
|
|
sdk.ChainIDSepolia,
|
|
|
|
sdk.ChainIDFantom,
|
|
|
|
sdk.ChainIDKarura,
|
|
|
|
sdk.ChainIDKlaytn,
|
|
|
|
sdk.ChainIDMoonbeam,
|
|
|
|
sdk.ChainIDOasis,
|
|
|
|
sdk.ChainIDOptimism,
|
|
|
|
sdk.ChainIDOptimismSepolia,
|
2024-04-22 10:26:07 -07:00
|
|
|
sdk.ChainIDPolygon,
|
2024-04-29 13:39:58 -07:00
|
|
|
sdk.ChainIDScroll,
|
2024-05-13 08:11:55 -07:00
|
|
|
sdk.ChainIDBlast,
|
2024-05-28 06:28:11 -07:00
|
|
|
sdk.ChainIDXLayer,
|
2024-05-13 08:11:55 -07:00
|
|
|
sdk.ChainIDPolygonSepolia:
|
2024-03-19 11:47:43 -07:00
|
|
|
return txHashLowerCaseWith0x(txHash)
|
|
|
|
case sdk.ChainIDSei, sdk.ChainIDWormchain:
|
|
|
|
return txHashLowerCaseWith0x(txHash)
|
|
|
|
default:
|
|
|
|
return txHash
|
|
|
|
}
|
|
|
|
}
|