Skip to content

Commit bedf920

Browse files
authored
Merge branch 'main' into depricate-govers-constant
2 parents 5113200 + 6a36a25 commit bedf920

File tree

1 file changed

+68
-1
lines changed

1 file changed

+68
-1
lines changed

pkg/evm/evm.go

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"crypto/ecdsa"
77
"fmt"
88
"math/big"
9+
"net/url"
10+
"strings"
911
"time"
1012

1113
"github.com/ava-labs/avalanche-cli/pkg/utils"
@@ -259,15 +261,80 @@ func SendTransaction(
259261
return err
260262
}
261263

264+
func FindOutScheme(rpcURL string) (ethclient.Client, string, error) {
265+
if b, err := HasScheme(rpcURL); err != nil {
266+
return nil, "", err
267+
} else if b {
268+
return nil, "", fmt.Errorf("url does have scheme")
269+
}
270+
notDeterminedErr := fmt.Errorf("url %s has no scheme and protocol could not be determined", rpcURL)
271+
// let's start with ws it always give same error for http/https/wss
272+
scheme := "ws://"
273+
ctx, cancel := utils.GetAPILargeContext()
274+
defer cancel()
275+
client, err := ethclient.DialContext(ctx, scheme+rpcURL)
276+
if err == nil {
277+
return client, scheme, nil
278+
} else if !strings.Contains(err.Error(), "websocket: bad handshake") {
279+
return nil, "", notDeterminedErr
280+
}
281+
// wss give specific errors for http/http
282+
scheme = "wss://"
283+
client, err = ethclient.DialContext(ctx, scheme+rpcURL)
284+
if err == nil {
285+
return client, scheme, nil
286+
} else if !strings.Contains(err.Error(), "websocket: bad handshake") && // may be https
287+
!strings.Contains(err.Error(), "first record does not look like a TLS handshake") { // may be http
288+
return nil, "", notDeterminedErr
289+
}
290+
// https/http discrimination based on sending a specific query
291+
scheme = "https://"
292+
client, err = ethclient.DialContext(ctx, scheme+rpcURL)
293+
if err == nil {
294+
_, err = client.ChainID(ctx)
295+
switch {
296+
case err == nil:
297+
return client, scheme, nil
298+
case strings.Contains(err.Error(), "server gave HTTP response to HTTPS client"):
299+
scheme = "http://"
300+
client, err = ethclient.DialContext(ctx, scheme+rpcURL)
301+
if err == nil {
302+
return client, scheme, nil
303+
}
304+
}
305+
}
306+
return nil, "", notDeterminedErr
307+
}
308+
309+
func HasScheme(rpcURL string) (bool, error) {
310+
if parsedURL, err := url.Parse(rpcURL); err != nil {
311+
if !strings.Contains(err.Error(), "first path segment in URL cannot contain colon") {
312+
return false, err
313+
}
314+
return false, nil
315+
} else if parsedURL.Scheme == "" {
316+
return false, nil
317+
}
318+
return true, nil
319+
}
320+
262321
func GetClient(rpcURL string) (ethclient.Client, error) {
263322
var (
264323
client ethclient.Client
265324
err error
266325
)
326+
hasScheme, err := HasScheme(rpcURL)
327+
if err != nil {
328+
return nil, err
329+
}
267330
for i := 0; i < repeatsOnFailure; i++ {
268331
ctx, cancel := utils.GetAPILargeContext()
269332
defer cancel()
270-
client, err = ethclient.DialContext(ctx, rpcURL)
333+
if hasScheme {
334+
client, err = ethclient.DialContext(ctx, rpcURL)
335+
} else {
336+
client, _, err = FindOutScheme(rpcURL)
337+
}
271338
if err == nil {
272339
break
273340
}

0 commit comments

Comments
 (0)