diff --git a/bindings/rocketpool/ec-interface.go b/bindings/rocketpool/ec-interface.go index 5e44a2377..393809f48 100644 --- a/bindings/rocketpool/ec-interface.go +++ b/bindings/rocketpool/ec-interface.go @@ -3,6 +3,7 @@ package rocketpool import ( "context" "math/big" + "time" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" @@ -102,4 +103,11 @@ type ExecutionClient interface { // SyncProgress retrieves the current progress of the sync algorithm. If there's // no sync currently running, it returns nil. SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error) + + /// ================= + /// Utility functions + /// ================= + + // LatestBlockTime returns the timestamp of the latest block + LatestBlockTime(ctx context.Context) (time.Time, error) } diff --git a/rocketpool-cli/node/withdraw-rpl.go b/rocketpool-cli/node/withdraw-rpl.go index a8c72ae56..54b7580ef 100644 --- a/rocketpool-cli/node/withdraw-rpl.go +++ b/rocketpool-cli/node/withdraw-rpl.go @@ -9,7 +9,6 @@ import ( "github.com/rocket-pool/smartnode/bindings/utils/eth" "github.com/urfave/cli" - "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/services/gas" "github.com/rocket-pool/smartnode/shared/services/rocketpool" cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" @@ -27,10 +26,6 @@ func nodeWithdrawRpl(c *cli.Context) error { return err } defer rp.Close() - ec, err := services.GetEthClient(c) - if err != nil { - return err - } // Get node status status, err := rp.NodeStatus() @@ -41,12 +36,6 @@ func nodeWithdrawRpl(c *cli.Context) error { var unstakingPeriodEnd time.Time if status.IsSaturnDeployed { - // Get the latest block time - latestBlockTimeUnix, err := services.GetEthClientLatestBlockTimestamp(ec) - if err != nil { - return err - } - latestBlockTime := time.Unix(int64(latestBlockTimeUnix), 0) fmt.Print("The RPL withdrawal process has changed in Saturn. It is now a 2-step process:") fmt.Println() fmt.Print("1. Request to unstake a certain RPL amount;") @@ -69,7 +58,7 @@ func nodeWithdrawRpl(c *cli.Context) error { fmt.Printf("") if status.UnstakingRPL.Cmp(big.NewInt(0)) > 0 { - if unstakingPeriodEnd.After(latestBlockTime) { + if unstakingPeriodEnd.After(status.LatestBlockTime) { fmt.Printf("You have %.6f RPL currently unstaking until %s.\n", status.UnstakingRPL, unstakingPeriodEnd.Format(TimeFormat)) } else { if !c.Bool("yes") || prompt.Confirm(fmt.Sprintf("You have %.6f RPL already unstaked. Would you like to withdraw it now?", eth.WeiToEth(status.UnstakingRPL))) { diff --git a/rocketpool/api/node/smoothing-pool.go b/rocketpool/api/node/smoothing-pool.go index 665fc510a..bc794a7ea 100644 --- a/rocketpool/api/node/smoothing-pool.go +++ b/rocketpool/api/node/smoothing-pool.go @@ -3,7 +3,6 @@ package node import ( "context" "fmt" - "time" "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/bindings/rewards" @@ -66,11 +65,10 @@ func getSmoothingPoolRegistrationStatus(c *cli.Context) (*api.GetSmoothingPoolRe } // Get the time the user can next change their opt-in status - latestBlockTimeUnix, err := services.GetEthClientLatestBlockTimestamp(ec) + latestBlockTime, err := ec.LatestBlockTime(context.Background()) if err != nil { return nil, err } - latestBlockTime := time.Unix(int64(latestBlockTimeUnix), 0) changeAvailableTime := regChangeTime.Add(intervalTime) response.TimeLeftUntilChangeable = changeAvailableTime.Sub(latestBlockTime) diff --git a/rocketpool/api/node/status.go b/rocketpool/api/node/status.go index 7da076899..5442c5b65 100644 --- a/rocketpool/api/node/status.go +++ b/rocketpool/api/node/status.go @@ -95,6 +95,8 @@ func getStatus(c *cli.Context) (*api.NodeStatusResponse, error) { // Sync var wg errgroup.Group + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() if saturnDeployed { wg.Go(func() error { @@ -189,6 +191,11 @@ func getStatus(c *cli.Context) (*api.NodeStatusResponse, error) { }) if saturnDeployed { + wg.Go(func() error { + var err error + response.LatestBlockTime, err = rp.Client.LatestBlockTime(ctx) + return err + }) // Get the node's locked RPL wg.Go(func() error { var err error @@ -417,6 +424,8 @@ func getStatus(c *cli.Context) (*api.NodeStatusResponse, error) { // Wait for data if err := wg.Wait(); err != nil { + // Cancel in-flight requests. + cancel() return nil, err } diff --git a/rocketpool/watchtower/generate-rewards-tree.go b/rocketpool/watchtower/generate-rewards-tree.go index d712d0770..5acfa6085 100644 --- a/rocketpool/watchtower/generate-rewards-tree.go +++ b/rocketpool/watchtower/generate-rewards-tree.go @@ -14,7 +14,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient" "github.com/rocket-pool/smartnode/bindings/rewards" "github.com/rocket-pool/smartnode/bindings/rocketpool" "github.com/rocket-pool/smartnode/shared/services" @@ -183,7 +182,7 @@ func (t *generateRewardsTree) generateRewardsTree(index uint64) { archiveEcUrl := t.cfg.Smartnode.ArchiveECUrl.Value.(string) if archiveEcUrl != "" { t.log.Printlnf("%s Primary EC cannot retrieve state for historical block %d, using archive EC [%s]", generationPrefix, elBlockHeader.Number.Uint64(), archiveEcUrl) - ec, err := ethclient.Dial(archiveEcUrl) + ec, err := services.NewEthClient(archiveEcUrl) if err != nil { t.handleError(fmt.Errorf("Error connecting to archive EC: %w", err)) return diff --git a/shared/services/ec-manager.go b/shared/services/ec-manager.go index be358eb1b..8a84c554b 100644 --- a/shared/services/ec-manager.go +++ b/shared/services/ec-manager.go @@ -23,8 +23,8 @@ import ( type ExecutionClientManager struct { primaryEcUrl string fallbackEcUrl string - primaryEc *ethclient.Client - fallbackEc *ethclient.Client + primaryEc *ethClient + fallbackEc *ethClient logger log.ColorLogger primaryReady bool fallbackReady bool @@ -32,7 +32,7 @@ type ExecutionClientManager struct { } // This is a signature for a wrapped ethclient.Client function -type ecFunction func(*ethclient.Client) (interface{}, error) +type ecFunction func(*ethClient) (interface{}, error) // Creates a new ExecutionClientManager instance based on the Rocket Pool config func NewExecutionClientManager(cfg *config.RocketPoolConfig) (*ExecutionClientManager, error) { @@ -80,8 +80,8 @@ func NewExecutionClientManager(cfg *config.RocketPoolConfig) (*ExecutionClientMa return &ExecutionClientManager{ primaryEcUrl: primaryEcUrl, fallbackEcUrl: fallbackEcUrl, - primaryEc: primaryEc, - fallbackEc: fallbackEc, + primaryEc: ðClient{primaryEc}, + fallbackEc: ðClient{fallbackEc}, logger: log.NewColorLogger(color.FgYellow), primaryReady: true, fallbackReady: fallbackEc != nil, @@ -96,7 +96,7 @@ func NewExecutionClientManager(cfg *config.RocketPoolConfig) (*ExecutionClientMa // CodeAt returns the code of the given account. This is needed to differentiate // between contract internal errors and the local chain being out of sync. func (p *ExecutionClientManager) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.CodeAt(ctx, contract, blockNumber) }) if err != nil { @@ -108,7 +108,7 @@ func (p *ExecutionClientManager) CodeAt(ctx context.Context, contract common.Add // CallContract executes an Ethereum contract call with the specified data as the // input. func (p *ExecutionClientManager) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.CallContract(ctx, call, blockNumber) }) if err != nil { @@ -123,7 +123,7 @@ func (p *ExecutionClientManager) CallContract(ctx context.Context, call ethereum // HeaderByHash returns the block header with the given hash. func (p *ExecutionClientManager) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.HeaderByHash(ctx, hash) }) if err != nil { @@ -135,7 +135,7 @@ func (p *ExecutionClientManager) HeaderByHash(ctx context.Context, hash common.H // HeaderByNumber returns a block header from the current canonical chain. If number is // nil, the latest known header is returned. func (p *ExecutionClientManager) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.HeaderByNumber(ctx, number) }) if err != nil { @@ -146,7 +146,7 @@ func (p *ExecutionClientManager) HeaderByNumber(ctx context.Context, number *big // PendingCodeAt returns the code of the given account in the pending state. func (p *ExecutionClientManager) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.PendingCodeAt(ctx, account) }) if err != nil { @@ -157,7 +157,7 @@ func (p *ExecutionClientManager) PendingCodeAt(ctx context.Context, account comm // PendingNonceAt retrieves the current pending nonce associated with an account. func (p *ExecutionClientManager) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.PendingNonceAt(ctx, account) }) if err != nil { @@ -169,7 +169,7 @@ func (p *ExecutionClientManager) PendingNonceAt(ctx context.Context, account com // SuggestGasPrice retrieves the currently suggested gas price to allow a timely // execution of a transaction. func (p *ExecutionClientManager) SuggestGasPrice(ctx context.Context) (*big.Int, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.SuggestGasPrice(ctx) }) if err != nil { @@ -181,7 +181,7 @@ func (p *ExecutionClientManager) SuggestGasPrice(ctx context.Context) (*big.Int, // SuggestGasTipCap retrieves the currently suggested 1559 priority fee to allow // a timely execution of a transaction. func (p *ExecutionClientManager) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.SuggestGasTipCap(ctx) }) if err != nil { @@ -196,7 +196,7 @@ func (p *ExecutionClientManager) SuggestGasTipCap(ctx context.Context) (*big.Int // transactions may be added or removed by miners, but it should provide a basis // for setting a reasonable default. func (p *ExecutionClientManager) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.EstimateGas(ctx, call) }) if err != nil { @@ -207,7 +207,7 @@ func (p *ExecutionClientManager) EstimateGas(ctx context.Context, call ethereum. // SendTransaction injects the transaction into the pending pool for execution. func (p *ExecutionClientManager) SendTransaction(ctx context.Context, tx *types.Transaction) error { - _, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + _, err := p.runFunction(func(client *ethClient) (interface{}, error) { return nil, client.SendTransaction(ctx, tx) }) return err @@ -222,7 +222,7 @@ func (p *ExecutionClientManager) SendTransaction(ctx context.Context, tx *types. // // TODO(karalabe): Deprecate when the subscription one can return past data too. func (p *ExecutionClientManager) FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.FilterLogs(ctx, query) }) if err != nil { @@ -234,7 +234,7 @@ func (p *ExecutionClientManager) FilterLogs(ctx context.Context, query ethereum. // SubscribeFilterLogs creates a background log filtering operation, returning // a subscription immediately, which can be used to stream the found events. func (p *ExecutionClientManager) SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.SubscribeFilterLogs(ctx, query, ch) }) if err != nil { @@ -250,7 +250,7 @@ func (p *ExecutionClientManager) SubscribeFilterLogs(ctx context.Context, query // TransactionReceipt returns the receipt of a transaction by transaction hash. // Note that the receipt is not available for pending transactions. func (p *ExecutionClientManager) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.TransactionReceipt(ctx, txHash) }) if err != nil { @@ -265,7 +265,7 @@ func (p *ExecutionClientManager) TransactionReceipt(ctx context.Context, txHash // BlockNumber returns the most recent block number func (p *ExecutionClientManager) BlockNumber(ctx context.Context) (uint64, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.BlockNumber(ctx) }) if err != nil { @@ -277,7 +277,7 @@ func (p *ExecutionClientManager) BlockNumber(ctx context.Context) (uint64, error // BalanceAt returns the wei balance of the given account. // The block number can be nil, in which case the balance is taken from the latest known block. func (p *ExecutionClientManager) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.BalanceAt(ctx, account, blockNumber) }) if err != nil { @@ -288,7 +288,7 @@ func (p *ExecutionClientManager) BalanceAt(ctx context.Context, account common.A // TransactionByHash returns the transaction with the given hash. func (p *ExecutionClientManager) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { tx, isPending, err := client.TransactionByHash(ctx, hash) result := []interface{}{tx, isPending} return result, err @@ -307,7 +307,7 @@ func (p *ExecutionClientManager) TransactionByHash(ctx context.Context, hash com // NonceAt returns the account nonce of the given account. // The block number can be nil, in which case the nonce is taken from the latest known block. func (p *ExecutionClientManager) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.NonceAt(ctx, account, blockNumber) }) if err != nil { @@ -319,7 +319,7 @@ func (p *ExecutionClientManager) NonceAt(ctx context.Context, account common.Add // SyncProgress retrieves the current progress of the sync algorithm. If there's // no sync currently running, it returns nil. func (p *ExecutionClientManager) SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error) { - result, err := p.runFunction(func(client *ethclient.Client) (interface{}, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { return client.SyncProgress(ctx) }) if err != nil { @@ -328,6 +328,16 @@ func (p *ExecutionClientManager) SyncProgress(ctx context.Context) (*ethereum.Sy return result.(*ethereum.SyncProgress), err } +func (p *ExecutionClientManager) LatestBlockTime(ctx context.Context) (time.Time, error) { + result, err := p.runFunction(func(client *ethClient) (interface{}, error) { + return client.LatestBlockTime(ctx) + }) + if err != nil { + return time.Time{}, err + } + return result.(time.Time), err +} + /// ================== /// Internal functions /// ================== @@ -387,7 +397,7 @@ func getNetworkNameFromId(networkId uint) string { } // Check the client status -func checkEcStatus(client *ethclient.Client) api.ClientStatus { +func checkEcStatus(client *ethClient) api.ClientStatus { status := api.ClientStatus{} diff --git a/shared/services/eth1.go b/shared/services/eth1.go deleted file mode 100644 index f444a4dd3..000000000 --- a/shared/services/eth1.go +++ /dev/null @@ -1,18 +0,0 @@ -package services - -import ( - "context" - - "github.com/rocket-pool/smartnode/bindings/rocketpool" -) - -func GetEthClientLatestBlockTimestamp(ec rocketpool.ExecutionClient) (uint64, error) { - // Get latest block - header, err := ec.HeaderByNumber(context.Background(), nil) - if err != nil { - return 0, err - } - - // Return block timestamp - return header.Time, nil -} diff --git a/shared/services/ethclient.go b/shared/services/ethclient.go new file mode 100644 index 000000000..5ecb2e2aa --- /dev/null +++ b/shared/services/ethclient.go @@ -0,0 +1,29 @@ +package services + +import ( + "context" + "time" + + "github.com/ethereum/go-ethereum/ethclient" +) + +type ethClient struct { + *ethclient.Client +} + +func NewEthClient(url string) (*ethClient, error) { + ec, err := ethclient.Dial(url) + if err != nil { + return nil, err + } + return ðClient{ec}, nil +} + +func (c *ethClient) LatestBlockTime(ctx context.Context) (time.Time, error) { + header, err := c.HeaderByNumber(ctx, nil) + if err != nil { + return time.Time{}, err + } + + return time.Unix(int64(header.Time), 0), nil +} diff --git a/shared/services/requirements.go b/shared/services/requirements.go index 7b72fa663..a6c249961 100644 --- a/shared/services/requirements.go +++ b/shared/services/requirements.go @@ -582,16 +582,15 @@ func waitBeaconClientSynced(c *cli.Context, verbose bool, timeout int64) (bool, // Confirm the EC's latest block is within the threshold of the current system clock func IsSyncWithinThreshold(ec rocketpool.ExecutionClient) (bool, time.Time, error) { - timestamp, err := GetEthClientLatestBlockTimestamp(ec) + t, err := ec.LatestBlockTime(context.Background()) if err != nil { return false, time.Time{}, err } // Return true if the latest block is under the threshold - blockTime := time.Unix(int64(timestamp), 0) - if time.Since(blockTime) < ethClientRecentBlockThreshold { - return true, blockTime, nil + if time.Since(t) < ethClientRecentBlockThreshold { + return true, t, nil } - return false, blockTime, nil + return false, t, nil } diff --git a/shared/services/services.go b/shared/services/services.go index e50dccf08..ee288be5d 100644 --- a/shared/services/services.go +++ b/shared/services/services.go @@ -92,6 +92,14 @@ func GetEthClient(c *cli.Context) (*ExecutionClientManager, error) { return ec, nil } +func dialProtectedEthClient(url string) (*ethClient, error) { + ec, err := ethclient.Dial(url) + if err != nil { + return nil, err + } + return ðClient{ec}, nil +} + func GetRocketPool(c *cli.Context) (*rocketpool.RocketPool, error) { cfg, err := getConfig(c) if err != nil { @@ -100,7 +108,7 @@ func GetRocketPool(c *cli.Context) (*rocketpool.RocketPool, error) { var ec rocketpool.ExecutionClient if c.GlobalBool("use-protected-api") { url := cfg.Smartnode.GetFlashbotsProtectUrl() - ec, err = ethclient.Dial(url) + ec, err = dialProtectedEthClient(url) } else { ec, err = getEthClient(c, cfg) } diff --git a/shared/services/state/cli/cli.go b/shared/services/state/cli/cli.go index b9c8c8ba2..1a2f824b2 100644 --- a/shared/services/state/cli/cli.go +++ b/shared/services/state/cli/cli.go @@ -7,8 +7,8 @@ import ( "os" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" "github.com/rocket-pool/smartnode/bindings/rocketpool" + "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/services/beacon/client" "github.com/rocket-pool/smartnode/shared/services/config" "github.com/rocket-pool/smartnode/shared/services/state" @@ -46,7 +46,7 @@ func main() { os.Exit(1) } - ec, err := ethclient.Dial(*elFlag) + ec, err := services.NewEthClient(*elFlag) if err != nil { fmt.Fprintf(os.Stderr, "Error connecting to execution node: %v\n", err) os.Exit(1) diff --git a/shared/types/api/node.go b/shared/types/api/node.go index 8ad71fe49..23441ce42 100644 --- a/shared/types/api/node.go +++ b/shared/types/api/node.go @@ -98,6 +98,7 @@ type NodeStatusResponse struct { UnstakingRPL *big.Int `json:"unstakingRPL"` LastRPLUnstakeTime time.Time `json:"lastRPLUnstakeTime"` UnstakingPeriodDuration time.Duration `json:"unstakingPeriodDuration"` + LatestBlockTime time.Time `json:"latestBlockTime"` } type NodeAlert struct { diff --git a/shared/utils/eth1/eth1.go b/shared/utils/eth1/eth1.go index 50044da42..d2a5874de 100644 --- a/shared/utils/eth1/eth1.go +++ b/shared/utils/eth1/eth1.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient" "github.com/rocket-pool/smartnode/bindings/rocketpool" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/services/config" @@ -83,7 +82,7 @@ func GetBestApiClient(primary *rocketpool.RocketPool, cfg *config.RocketPoolConf archiveEcUrl := cfg.Smartnode.ArchiveECUrl.Value.(string) if archiveEcUrl != "" { printMessage(fmt.Sprintf("Primary EC cannot retrieve state for historical block %d, using archive EC [%s]", blockNumber.Uint64(), archiveEcUrl)) - ec, err := ethclient.Dial(archiveEcUrl) + ec, err := services.NewEthClient(archiveEcUrl) if err != nil { return nil, fmt.Errorf("Error connecting to archive EC: %w", err) } diff --git a/treegen/tree-gen.go b/treegen/tree-gen.go index 76afd1e3d..4b7e34abc 100644 --- a/treegen/tree-gen.go +++ b/treegen/tree-gen.go @@ -15,11 +15,11 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" "github.com/fatih/color" "github.com/rocket-pool/smartnode/bindings/rewards" "github.com/rocket-pool/smartnode/bindings/rocketpool" "github.com/rocket-pool/smartnode/bindings/utils/eth" + "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/services/beacon" "github.com/rocket-pool/smartnode/shared/services/beacon/client" "github.com/rocket-pool/smartnode/shared/services/config" @@ -125,7 +125,7 @@ func GenerateTree(c *cli.Context) error { } // Create the EC and BN clients - ec, err := ethclient.Dial(ecUrl) + ec, err := services.NewEthClient(ecUrl) if err != nil { return fmt.Errorf("error connecting to the EC: %w", err) }