diff --git a/rocketpool-cli/rocketpool-cli.go b/rocketpool-cli/rocketpool-cli.go index cbc102634..0715dd652 100644 --- a/rocketpool-cli/rocketpool-cli.go +++ b/rocketpool-cli/rocketpool-cli.go @@ -145,6 +145,8 @@ ______ _ _ ______ _ if cfg.Smartnode.GetRplFaucetAddress() != "" { faucet.RegisterCommands(app, "faucet", []string{"f"}) } + + service.RegisterCommands(app, "service", []string{"s"}, cfg) } minipool.RegisterCommands(app, "minipool", []string{"m"}) @@ -152,7 +154,6 @@ ______ _ _ ______ _ node.RegisterCommands(app, "node", []string{"n"}) odao.RegisterCommands(app, "odao", []string{"o"}) queue.RegisterCommands(app, "queue", []string{"q"}) - service.RegisterCommands(app, "service", []string{"s"}) wallet.RegisterCommands(app, "wallet", []string{"w"}) app.Before = func(c *cli.Context) error { diff --git a/rocketpool-cli/service/commands.go b/rocketpool-cli/service/commands.go index 6f84d52d7..4a9ad55e7 100644 --- a/rocketpool-cli/service/commands.go +++ b/rocketpool-cli/service/commands.go @@ -80,17 +80,16 @@ func createFlagsFromConfigParams(sectionName string, params []*cfgtypes.Paramete } // Register commands -func RegisterCommands(app *cli.App, name string, aliases []string) { +func RegisterCommands(app *cli.App, name string, aliases []string, cfg *config.RocketPoolConfig) { configFlags := []cli.Flag{} - cfgTemplate := config.NewRocketPoolConfig("", false) - network := cfgTemplate.Smartnode.Network.Value.(cfgtypes.Network) + network := cfg.Smartnode.Network.Value.(cfgtypes.Network) // Root params - configFlags = createFlagsFromConfigParams("", cfgTemplate.GetParameters(), configFlags, network) + configFlags = createFlagsFromConfigParams("", cfg.GetParameters(), configFlags, network) // Subconfigs - for sectionName, subconfig := range cfgTemplate.GetSubconfigs() { + for sectionName, subconfig := range cfg.GetSubconfigs() { configFlags = createFlagsFromConfigParams(sectionName, subconfig.GetParameters(), configFlags, network) } diff --git a/rocketpool-cli/service/service.go b/rocketpool-cli/service/service.go index 6f1d9df03..2486265e0 100644 --- a/rocketpool-cli/service/service.go +++ b/rocketpool-cli/service/service.go @@ -1628,7 +1628,7 @@ func resyncEth2(c *cli.Context) error { // Generate a YAML file that shows the current configuration schema, including all of the parameters and their descriptions func getConfigYaml(c *cli.Context) error { - cfg := config.NewRocketPoolConfig("", false) + cfg := config.NewRocketPoolConfig("", false, config.NewNetworksConfig()) bytes, err := yaml.Marshal(cfg) if err != nil { return fmt.Errorf("error serializing configuration schema: %w", err) diff --git a/shared/services/config/networks-config.go b/shared/services/config/networks-config.go new file mode 100644 index 000000000..acc32dd37 --- /dev/null +++ b/shared/services/config/networks-config.go @@ -0,0 +1,87 @@ +package config + +import ( + "fmt" + "os" + "path" + + "github.com/rocket-pool/smartnode/shared/types/config" + "gopkg.in/yaml.v2" +) + +const ( + defaultNetworksConfigPath = "networks-default.yml" + extraNetworksConfigPath = "networks-extra.yml" +) + +type NetworksConfig struct { + Networks []*config.NetworkInfo `yaml:"networks"` + networkLookup map[config.Network]*config.NetworkInfo +} + +func NewNetworksConfig() *NetworksConfig { + return &NetworksConfig{ + Networks: make([]*config.NetworkInfo, 0), + networkLookup: make(map[config.Network]*config.NetworkInfo), + } +} + +func LoadNetworksFromFile(configPath string) (*NetworksConfig, error) { + _, err := os.Stat(configPath) + if os.IsNotExist(err) { + return nil, fmt.Errorf("config path does not exist: %s", configPath) + } + + filePath := path.Join(configPath, defaultNetworksConfigPath) + defaultNetworks, err := loadNetworksFile(filePath) + if err != nil { + return nil, fmt.Errorf("could not load default networks file: %w", err) + } + + filePath = path.Join(configPath, extraNetworksConfigPath) + _, err = os.Stat(filePath) + if os.IsNotExist(err) { + // if the file didn't exist, we just use the default networks + return defaultNetworks, nil + } + extraNetworks, err := loadNetworksFile(filePath) + if err != nil { + return nil, fmt.Errorf("could not load extra networks file: %w", err) + } + defaultNetworks.Networks = append(defaultNetworks.Networks, extraNetworks.Networks...) + + // save the networks for lookup + defaultNetworks.networkLookup = make(map[config.Network]*config.NetworkInfo) // Update the type of networkLookup + for _, network := range defaultNetworks.Networks { + defaultNetworks.networkLookup[config.Network(network.Name)] = network // Update the assignment statement with type assertion + } + + return defaultNetworks, nil +} + +func loadNetworksFile(filePath string) (*NetworksConfig, error) { + bytes, err := os.ReadFile(filePath) + if err != nil { + return nil, fmt.Errorf("could not read default networks file: %w", err) + } + + networks := NetworksConfig{} + err = yaml.Unmarshal(bytes, &networks) + if err != nil { + return nil, fmt.Errorf("could not unmarshal default networks file: %w", err) + } + + return &networks, nil +} + +func (nc *NetworksConfig) AllNetworks() []*config.NetworkInfo { + return nc.Networks +} + +func (nc *NetworksConfig) GetNetwork(name config.Network) *config.NetworkInfo { + network, ok := nc.networkLookup[name] + if !ok { + return nil + } + return network +} diff --git a/shared/services/config/rocket-pool-config.go b/shared/services/config/rocket-pool-config.go index fa850e2bb..83ce98275 100644 --- a/shared/services/config/rocket-pool-config.go +++ b/shared/services/config/rocket-pool-config.go @@ -58,6 +58,8 @@ type RocketPoolConfig struct { IsNativeMode bool `yaml:"-"` + networks *NetworksConfig `yaml:"-"` + // Execution client settings ExecutionClientMode config.Parameter `yaml:"executionClientMode,omitempty"` ExecutionClient config.Parameter `yaml:"executionClient,omitempty"` @@ -165,9 +167,13 @@ func LoadFromFile(path string) (*RocketPoolConfig, error) { if err := yaml.Unmarshal(configBytes, &settings); err != nil { return nil, fmt.Errorf("could not parse settings file: %w", err) } - + // now load the networks: + networks, err := LoadNetworksFromFile(filepath.Dir(path)) + if err != nil { + return nil, fmt.Errorf("could not load networks file: %w", err) + } // Deserialize it into a config object - cfg := NewRocketPoolConfig(filepath.Dir(path), false) + cfg := NewRocketPoolConfig(filepath.Dir(path), false, networks) err = cfg.Deserialize(settings) if err != nil { return nil, fmt.Errorf("could not deserialize settings file: %w", err) @@ -178,7 +184,7 @@ func LoadFromFile(path string) (*RocketPoolConfig, error) { } // Creates a new Rocket Pool configuration instance -func NewRocketPoolConfig(rpDir string, isNativeMode bool) *RocketPoolConfig { +func NewRocketPoolConfig(rpDir string, isNativeMode bool, networks *NetworksConfig) *RocketPoolConfig { clientModes := []config.ParameterOption{{ Name: "Locally Managed", @@ -194,6 +200,7 @@ func NewRocketPoolConfig(rpDir string, isNativeMode bool) *RocketPoolConfig { Title: "Top-level Settings", RocketPoolDirectory: rpDir, IsNativeMode: isNativeMode, + networks: networks, ExecutionClientMode: config.Parameter{ ID: "executionClientMode", @@ -503,7 +510,7 @@ func getAugmentedEcDescription(client config.ExecutionClient, originalDescriptio // Create a copy of this configuration. func (cfg *RocketPoolConfig) CreateCopy() *RocketPoolConfig { - newConfig := NewRocketPoolConfig(cfg.RocketPoolDirectory, cfg.IsNativeMode) + newConfig := NewRocketPoolConfig(cfg.RocketPoolDirectory, cfg.IsNativeMode, cfg.networks) // Set the network network := cfg.Smartnode.Network.Value.(config.Network) diff --git a/shared/services/config/smartnode-config.go b/shared/services/config/smartnode-config.go index 80d56b390..2da24a292 100644 --- a/shared/services/config/smartnode-config.go +++ b/shared/services/config/smartnode-config.go @@ -3,7 +3,6 @@ package config import ( "fmt" "path/filepath" - "strings" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/shared" @@ -102,103 +101,6 @@ type SmartnodeConfig struct { // The path of the records folder where snapshots of rolling record info is stored during a rewards interval RecordsPath config.Parameter `yaml:"recordsPath,omitempty"` - - /////////////////////////// - // Non-editable settings // - /////////////////////////// - - // The URL to provide the user so they can follow pending transactions - txWatchUrl map[config.Network]string `yaml:"-"` - - // The URL to use for staking rETH - stakeUrl map[config.Network]string `yaml:"-"` - - // The map of networks to execution chain IDs - chainID map[config.Network]uint `yaml:"-"` - - // The contract address of RocketStorage - storageAddress map[config.Network]string `yaml:"-"` - - // The contract address of the RPL token - rplTokenAddress map[config.Network]string `yaml:"-"` - - // The contract address of the RPL faucet - rplFaucetAddress map[config.Network]string `yaml:"-"` - - // The contract address for Snapshot delegation - snapshotDelegationAddress map[config.Network]string `yaml:"-"` - - // The Snapshot API domain - snapshotApiDomain map[config.Network]string `yaml:"-"` - - // The contract address of rETH - rethAddress map[config.Network]string `yaml:"-"` - - // The contract address of rocketRewardsPool from v1.0.0 - v1_0_0_RewardsPoolAddress map[config.Network]string `yaml:"-"` - - // The contract address of rocketClaimNode from v1.0.0 - v1_0_0_ClaimNodeAddress map[config.Network]string `yaml:"-"` - - // The contract address of rocketClaimTrustedNode from v1.0.0 - v1_0_0_ClaimTrustedNodeAddress map[config.Network]string `yaml:"-"` - - // The contract address of rocketMinipoolManager from v1.0.0 - v1_0_0_MinipoolManagerAddress map[config.Network]string `yaml:"-"` - - // The contract address of rocketNetworkPrices from v1.1.0 - v1_1_0_NetworkPricesAddress map[config.Network]string `yaml:"-"` - - // The contract address of rocketNodeStaking from v1.1.0 - v1_1_0_NodeStakingAddress map[config.Network]string `yaml:"-"` - - // The contract address of rocketNodeDeposit from v1.1.0 - v1_1_0_NodeDepositAddress map[config.Network]string `yaml:"-"` - - // The contract address of rocketMinipoolQueue from v1.1.0 - v1_1_0_MinipoolQueueAddress map[config.Network]string `yaml:"-"` - - // The contract address of rocketMinipoolFactory from v1.1.0 - v1_1_0_MinipoolFactoryAddress map[config.Network]string `yaml:"-"` - - // Addresses for RocketRewardsPool that have been upgraded during development - previousRewardsPoolAddresses map[config.Network][]common.Address `yaml:"-"` - - // The RocketOvmPriceMessenger Optimism address for each network - optimismPriceMessengerAddress map[config.Network]string `yaml:"-"` - - // The RocketPolygonPriceMessenger Polygon address for each network - polygonPriceMessengerAddress map[config.Network]string `yaml:"-"` - - // The RocketArbitumPriceMessenger Arbitrum address for each network - arbitrumPriceMessengerAddress map[config.Network]string `yaml:"-"` - - // The RocketArbitumPriceMessengerV2 Arbitrum address for each network - arbitrumPriceMessengerAddressV2 map[config.Network]string `yaml:"-"` - - // The RocketZkSyncPriceMessenger zkSyncEra address for each network - zkSyncEraPriceMessengerAddress map[config.Network]string `yaml:"-"` - - // The RocketBasePriceMessenger Base address for each network - basePriceMessengerAddress map[config.Network]string `yaml:"-"` - - // The RocketScrollPriceMessenger Scroll address for each network - scrollPriceMessengerAddress map[config.Network]string `yaml:"-"` - - // The Scroll L2 message fee estimator address for each network - scrollFeeEstimatorAddress map[config.Network]string `yaml:"-"` - - // The UniswapV3 pool address for each network (used for RPL price TWAP info) - rplTwapPoolAddress map[config.Network]string `yaml:"-"` - - // The multicall contract address - multicallAddress map[config.Network]string `yaml:"-"` - - // The BalanceChecker contract address - balancebatcherAddress map[config.Network]string `yaml:"-"` - - // The FlashBots Protect RPC endpoint - flashbotsProtectUrl map[config.Network]string `yaml:"-"` } // Generates a new Smartnode configuration @@ -250,7 +152,7 @@ func NewSmartnodeConfig(cfg *RocketPoolConfig) *SmartnodeConfig { AffectsContainers: []config.ContainerID{config.ContainerID_Api, config.ContainerID_Node, config.ContainerID_Watchtower, config.ContainerID_Eth1, config.ContainerID_Eth2, config.ContainerID_Validator}, CanBeBlank: false, OverwriteOnUpgrade: false, - Options: getNetworkOptions(), + Options: getNetworkOptions(cfg.networks.AllNetworks()), }, ManualMaxFee: config.Parameter{ @@ -406,194 +308,6 @@ func NewSmartnodeConfig(cfg *RocketPoolConfig) *SmartnodeConfig { CanBeBlank: false, OverwriteOnUpgrade: false, }, - - txWatchUrl: map[config.Network]string{ - config.Network_Mainnet: "https://etherscan.io/tx", - config.Network_Devnet: "https://holesky.etherscan.io/tx", - config.Network_Holesky: "https://holesky.etherscan.io/tx", - }, - - stakeUrl: map[config.Network]string{ - config.Network_Mainnet: "https://stake.rocketpool.net", - config.Network_Devnet: "TBD", - config.Network_Holesky: "TBD", - }, - - chainID: map[config.Network]uint{ - config.Network_Mainnet: 1, // Mainnet - config.Network_Devnet: 17000, // Also Holesky - config.Network_Holesky: 17000, // Holesky - }, - - storageAddress: map[config.Network]string{ - config.Network_Mainnet: "0x1d8f8f00cfa6758d7bE78336684788Fb0ee0Fa46", - config.Network_Devnet: "0x6A18E47f8CcB453Dd0894AC003f74BEE7e47A368", - config.Network_Holesky: "0x594Fb75D3dc2DFa0150Ad03F99F97817747dd4E1", - }, - - rplTokenAddress: map[config.Network]string{ - config.Network_Mainnet: "0xD33526068D116cE69F19A9ee46F0bd304F21A51f", - config.Network_Devnet: "0x09b6aEF57B580f5CB46746BA59ed312Ba80E8Ad4", - config.Network_Holesky: "0x1Cc9cF5586522c6F483E84A19c3C2B0B6d027bF0", - }, - - rplFaucetAddress: map[config.Network]string{ - config.Network_Mainnet: "", - config.Network_Devnet: "0x218a718A1B23B13737E2F566Dd45730E8DAD451b", - config.Network_Holesky: "0xb4565BDe40Cb22282D7287A839c4ce8534674070", - }, - - rethAddress: map[config.Network]string{ - config.Network_Mainnet: "0xae78736Cd615f374D3085123A210448E74Fc6393", - config.Network_Devnet: "0x2DF914425da6d0067EF1775AfDBDd7B24fc8100E", - config.Network_Holesky: "0x7322c24752f79c05FFD1E2a6FCB97020C1C264F1", - }, - - v1_0_0_RewardsPoolAddress: map[config.Network]string{ - config.Network_Mainnet: "0xA3a18348e6E2d3897B6f2671bb8c120e36554802", - config.Network_Devnet: "0x4A1b5Ab9F6C36E7168dE5F994172028Ca8554e02", - config.Network_Holesky: "", - }, - - v1_0_0_ClaimNodeAddress: map[config.Network]string{ - config.Network_Mainnet: "0x899336A2a86053705E65dB61f52C686dcFaeF548", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - v1_0_0_ClaimTrustedNodeAddress: map[config.Network]string{ - config.Network_Mainnet: "0x6af730deB0463b432433318dC8002C0A4e9315e8", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - v1_0_0_MinipoolManagerAddress: map[config.Network]string{ - config.Network_Mainnet: "0x6293B8abC1F36aFB22406Be5f96D893072A8cF3a", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - v1_1_0_NetworkPricesAddress: map[config.Network]string{ - config.Network_Mainnet: "0xd3f500F550F46e504A4D2153127B47e007e11166", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - v1_1_0_NodeStakingAddress: map[config.Network]string{ - config.Network_Mainnet: "0xA73ec45Fe405B5BFCdC0bF4cbc9014Bb32a01cd2", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - v1_1_0_NodeDepositAddress: map[config.Network]string{ - config.Network_Mainnet: "0x1Cc9cF5586522c6F483E84A19c3C2B0B6d027bF0", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - v1_1_0_MinipoolQueueAddress: map[config.Network]string{ - config.Network_Mainnet: "0x5870dA524635D1310Dc0e6F256Ce331012C9C19E", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - v1_1_0_MinipoolFactoryAddress: map[config.Network]string{ - config.Network_Mainnet: "0x54705f80D7C51Fcffd9C659ce3f3C9a7dCCf5788", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - snapshotDelegationAddress: map[config.Network]string{ - config.Network_Mainnet: "0x469788fE6E9E9681C6ebF3bF78e7Fd26Fc015446", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - snapshotApiDomain: map[config.Network]string{ - config.Network_Mainnet: "hub.snapshot.org", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - previousRewardsPoolAddresses: map[config.Network][]common.Address{ - config.Network_Mainnet: { - common.HexToAddress("0x594Fb75D3dc2DFa0150Ad03F99F97817747dd4E1"), - }, - config.Network_Devnet: {}, - config.Network_Holesky: {}, - }, - - optimismPriceMessengerAddress: map[config.Network]string{ - config.Network_Mainnet: "0xdddcf2c25d50ec22e67218e873d46938650d03a7", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - polygonPriceMessengerAddress: map[config.Network]string{ - config.Network_Mainnet: "0xb1029Ac2Be4e08516697093e2AFeC435057f3511", - config.Network_Devnet: "0x6D736da1dC2562DBeA9998385A0A27d8c2B2793e", - config.Network_Holesky: "", - }, - - arbitrumPriceMessengerAddress: map[config.Network]string{ - config.Network_Mainnet: "0x05330300f829AD3fC8f33838BC88CFC4093baD53", - config.Network_Devnet: "0x2b52479F6ea009907e46fc43e91064D1b92Fdc86", - config.Network_Holesky: "", - }, - - arbitrumPriceMessengerAddressV2: map[config.Network]string{ - config.Network_Mainnet: "0x312FcFB03eC9B1Ea38CB7BFCd26ee7bC3b505aB1", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - zkSyncEraPriceMessengerAddress: map[config.Network]string{ - config.Network_Mainnet: "0x6cf6CB29754aEBf88AF12089224429bD68b0b8c8", - config.Network_Devnet: "0x3Fd49431bD05875AeD449Bc8C07352942A7fBA75", - config.Network_Holesky: "", - }, - - basePriceMessengerAddress: map[config.Network]string{ - config.Network_Mainnet: "0x64A5856869C06B0188C84A5F83d712bbAc03517d", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - scrollPriceMessengerAddress: map[config.Network]string{ - config.Network_Mainnet: "0x0f22dc9b9c03757d4676539203d7549c8f22c15c", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - scrollFeeEstimatorAddress: map[config.Network]string{ - config.Network_Mainnet: "0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B", - config.Network_Devnet: "", - config.Network_Holesky: "", - }, - - rplTwapPoolAddress: map[config.Network]string{ - config.Network_Mainnet: "0xe42318ea3b998e8355a3da364eb9d48ec725eb45", - config.Network_Devnet: "0x5cE71E603B138F7e65029Cc1918C0566ed0dBD4B", - config.Network_Holesky: "0x7bb10d2a3105ed5cc150c099a06cafe43d8aa15d", - }, - - multicallAddress: map[config.Network]string{ - config.Network_Mainnet: "0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696", - config.Network_Devnet: "0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696", - config.Network_Holesky: "0x0540b786f03c9491f3a2ab4b0e3ae4ecd4f63ce7", - }, - - balancebatcherAddress: map[config.Network]string{ - config.Network_Mainnet: "0xb1f8e55c7f64d203c1400b9d8555d050f94adf39", - config.Network_Devnet: "0x9788C4E93f9002a7ad8e72633b11E8d1ecd51f9b", - config.Network_Holesky: "0xfAa2e7C84eD801dd9D27Ac1ed957274530796140", - }, - - flashbotsProtectUrl: map[config.Network]string{ - config.Network_Mainnet: "https://rpc.flashbots.net/", - config.Network_Devnet: "https://rpc-holesky.flashbots.net/", - config.Network_Holesky: "", - }, } } @@ -622,16 +336,26 @@ func (cfg *SmartnodeConfig) GetParameters() []*config.Parameter { // Getters for the non-editable parameters +// Gets the currently chosen network's configuration +func (cfg *SmartnodeConfig) GetNetworkInfo() *config.NetworkInfo { + network := cfg.parent.networks.GetNetwork(cfg.Network.Value.(config.Network)) + if network == nil { + fmt.Printf("Network info not found for network %s\n", cfg.Network.Value.(string)) + return nil + } + return network +} + func (cfg *SmartnodeConfig) GetTxWatchUrl() string { - return cfg.txWatchUrl[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().TxWatchUrl } func (cfg *SmartnodeConfig) GetStakeUrl() string { - return cfg.stakeUrl[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().StakeUrl } func (cfg *SmartnodeConfig) GetChainID() uint { - return cfg.chainID[cfg.Network.Value.(config.Network)] + return uint(cfg.GetNetworkInfo().ChainID) } func (cfg *SmartnodeConfig) GetWalletPath() string { @@ -703,19 +427,19 @@ func (cfg *SmartnodeConfig) GetCustomKeyPasswordFilePath() string { } func (cfg *SmartnodeConfig) GetStorageAddress() string { - return cfg.storageAddress[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.Storage } func (cfg *SmartnodeConfig) GetRplTokenAddress() string { - return cfg.rplTokenAddress[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.RplToken } func (cfg *SmartnodeConfig) GetRplFaucetAddress() string { - return cfg.rplFaucetAddress[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.RplFaucet } func (cfg *SmartnodeConfig) GetSnapshotDelegationAddress() string { - return cfg.snapshotDelegationAddress[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.SnapshotDelegation } func (cfg *SmartnodeConfig) GetSmartnodeContainerTag() string { @@ -731,7 +455,7 @@ func (cfg *SmartnodeConfig) GetEcMigratorContainerTag() string { } func (cfg *SmartnodeConfig) GetSnapshotApiDomain() string { - return cfg.snapshotApiDomain[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().SnapshotApiDomain } func (cfg *SmartnodeConfig) GetVotingSnapshotID() [32]byte { @@ -752,7 +476,7 @@ func (cfg *SmartnodeConfig) GetConfigTitle() string { } func (cfg *SmartnodeConfig) GetRethAddress() common.Address { - return common.HexToAddress(cfg.rethAddress[cfg.Network.Value.(config.Network)]) + return common.HexToAddress(cfg.GetNetworkInfo().Addresses.Reth) } func getDefaultDataDir(config *RocketPoolConfig) string { @@ -804,113 +528,105 @@ func (cfg *SmartnodeConfig) GetFeeRecipientFilePath() string { } func (cfg *SmartnodeConfig) GetV100RewardsPoolAddress() common.Address { - return common.HexToAddress(cfg.v1_0_0_RewardsPoolAddress[cfg.Network.Value.(config.Network)]) + return common.HexToAddress(cfg.GetNetworkInfo().Addresses.V1_0_0_RewardsPool) } func (cfg *SmartnodeConfig) GetV100ClaimNodeAddress() common.Address { - return common.HexToAddress(cfg.v1_0_0_ClaimNodeAddress[cfg.Network.Value.(config.Network)]) + return common.HexToAddress(cfg.GetNetworkInfo().Addresses.V1_0_0_ClaimNode) } func (cfg *SmartnodeConfig) GetV100ClaimTrustedNodeAddress() common.Address { - return common.HexToAddress(cfg.v1_0_0_ClaimTrustedNodeAddress[cfg.Network.Value.(config.Network)]) + return common.HexToAddress(cfg.GetNetworkInfo().Addresses.V1_0_0_ClaimTrustedNode) } func (cfg *SmartnodeConfig) GetV100MinipoolManagerAddress() common.Address { - return common.HexToAddress(cfg.v1_0_0_MinipoolManagerAddress[cfg.Network.Value.(config.Network)]) + return common.HexToAddress(cfg.GetNetworkInfo().Addresses.V1_0_0_MinipoolManager) } func (cfg *SmartnodeConfig) GetV110NetworkPricesAddress() common.Address { - return common.HexToAddress(cfg.v1_1_0_NetworkPricesAddress[cfg.Network.Value.(config.Network)]) + return common.HexToAddress(cfg.GetNetworkInfo().Addresses.V1_1_0_NetworkPrices) } func (cfg *SmartnodeConfig) GetV110NodeStakingAddress() common.Address { - return common.HexToAddress(cfg.v1_1_0_NodeStakingAddress[cfg.Network.Value.(config.Network)]) + return common.HexToAddress(cfg.GetNetworkInfo().Addresses.V1_1_0_NodeStaking) } func (cfg *SmartnodeConfig) GetV110NodeDepositAddress() common.Address { - return common.HexToAddress(cfg.v1_1_0_NodeDepositAddress[cfg.Network.Value.(config.Network)]) + return common.HexToAddress(cfg.GetNetworkInfo().Addresses.V1_1_0_NodeDeposit) } func (cfg *SmartnodeConfig) GetV110MinipoolQueueAddress() common.Address { - return common.HexToAddress(cfg.v1_1_0_MinipoolQueueAddress[cfg.Network.Value.(config.Network)]) + return common.HexToAddress(cfg.GetNetworkInfo().Addresses.V1_1_0_MinipoolQueue) } func (cfg *SmartnodeConfig) GetV110MinipoolFactoryAddress() common.Address { - return common.HexToAddress(cfg.v1_1_0_MinipoolFactoryAddress[cfg.Network.Value.(config.Network)]) + return common.HexToAddress(cfg.GetNetworkInfo().Addresses.V1_1_0_MinipoolFactory) } func (cfg *SmartnodeConfig) GetPreviousRewardsPoolAddresses() []common.Address { - return cfg.previousRewardsPoolAddresses[cfg.Network.Value.(config.Network)] + addresses := make([]common.Address, 0, len(cfg.GetNetworkInfo().Addresses.PreviousRewardsPools)) + for _, address := range cfg.GetNetworkInfo().Addresses.PreviousRewardsPools { + addresses = append(addresses, common.HexToAddress(address)) + } + return addresses } func (cfg *SmartnodeConfig) GetOptimismMessengerAddress() string { - return cfg.optimismPriceMessengerAddress[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.OptimismPriceMessenger } func (cfg *SmartnodeConfig) GetPolygonMessengerAddress() string { - return cfg.polygonPriceMessengerAddress[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.PolygonPriceMessenger } func (cfg *SmartnodeConfig) GetArbitrumMessengerAddress() string { - return cfg.arbitrumPriceMessengerAddress[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.ArbitrumPriceMessenger } func (cfg *SmartnodeConfig) GetArbitrumMessengerAddressV2() string { - return cfg.arbitrumPriceMessengerAddressV2[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.ArbitrumPriceMessengerV2 } func (cfg *SmartnodeConfig) GetZkSyncEraMessengerAddress() string { - return cfg.zkSyncEraPriceMessengerAddress[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.ZkSyncEraPriceMessenger } func (cfg *SmartnodeConfig) GetBaseMessengerAddress() string { - return cfg.basePriceMessengerAddress[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.BasePriceMessenger } func (cfg *SmartnodeConfig) GetScrollMessengerAddress() string { - return cfg.scrollPriceMessengerAddress[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.ScrollPriceMessenger } func (cfg *SmartnodeConfig) GetScrollFeeEstimatorAddress() string { - return cfg.scrollFeeEstimatorAddress[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.ScrollFeeEstimator } func (cfg *SmartnodeConfig) GetRplTwapPoolAddress() string { - return cfg.rplTwapPoolAddress[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.RplTwapPool } func (cfg *SmartnodeConfig) GetMulticallAddress() string { - return cfg.multicallAddress[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.Multicall } func (cfg *SmartnodeConfig) GetBalanceBatcherAddress() string { - return cfg.balancebatcherAddress[cfg.Network.Value.(config.Network)] + return cfg.GetNetworkInfo().Addresses.Balancebatcher } func (cfg *SmartnodeConfig) GetFlashbotsProtectUrl() string { - return cfg.flashbotsProtectUrl[cfg.Network.Value.(config.Network)] -} - -func getNetworkOptions() []config.ParameterOption { - options := []config.ParameterOption{ - { - Name: "Ethereum Mainnet", - Description: "This is the real Ethereum main network, using real ETH and real RPL to make real validators.", - Value: config.Network_Mainnet, - }, { - Name: "Holesky Testnet", - Description: "This is the Holešky (Holešovice) test network, which is the next generation of long-lived testnets for Ethereum. It uses free fake ETH and free fake RPL to make fake validators.\nUse this if you want to practice running the Smartnode in a free, safe environment before moving to Mainnet.", - Value: config.Network_Holesky, - }, - } + return cfg.GetNetworkInfo().FlashbotsProtectUrl +} - if strings.HasSuffix(shared.RocketPoolVersion, "-dev") { +func getNetworkOptions(networks []*config.NetworkInfo) []config.ParameterOption { + var options []config.ParameterOption + for _, network := range networks { options = append(options, config.ParameterOption{ - Name: "Devnet", - Description: "This is a development network used by Rocket Pool engineers to test new features and contract upgrades before they are promoted to a Testnet for staging. You should not use this network unless invited to do so by the developers.", - Value: config.Network_Devnet, + Name: network.Label, + Description: network.Description, + Value: config.Network(network.Name), }) } - return options } diff --git a/shared/services/rocketpool/client.go b/shared/services/rocketpool/client.go index 29043d185..163e8afb6 100644 --- a/shared/services/rocketpool/client.go +++ b/shared/services/rocketpool/client.go @@ -227,7 +227,11 @@ func (c *Client) LoadConfig() (*config.RocketPoolConfig, bool, error) { } // Config wasn't loaded, but there was no error- we should create one. - return config.NewRocketPoolConfig(c.configPath, c.daemonPath != ""), true, nil + networks, err := config.LoadNetworksFromFile(c.configPath) + if err != nil { + return nil, false, fmt.Errorf("could not load networks file: %w", err) + } + return config.NewRocketPoolConfig(c.configPath, c.daemonPath != "", networks), true, nil } // Load the backup config diff --git a/shared/types/config/types.go b/shared/types/config/types.go index 14d220b07..43c2e4936 100644 --- a/shared/types/config/types.go +++ b/shared/types/config/types.go @@ -144,3 +144,83 @@ type MevRelay struct { Urls map[Network]string Regulated bool } + +// Describes a network that the smartnode system can use. +type NetworkInfo struct { + // A unique name for the network + Name string `yaml:"name"` + // A human-readable label for the network + Label string `yaml:"label"` + // A human-readable description of the network + Description string `yaml:"description"` + // The URL to provide the user so they can follow pending transactions + TxWatchUrl string `yaml:"txWatchUrl"` + // The URL to use for staking rETH + StakeUrl string `yaml:"stakeUrl"` + // Execution chain ID + ChainID uint64 `yaml:"chainID"` + // The Snapshot API domain + SnapshotApiDomain string `yaml:"snapshotApiDomain"` + // The FlashBots Protect RPC endpoint + FlashbotsProtectUrl string `yaml:"flashbotsProtectUrl"` + // Indicates if we support mevboost on the network + IsMevBoostSupported bool `yaml:"isMevBoostSupported"` + // The set of addresses we need for the network. + Addresses NetworkAddresses `yaml:"addresses"` +} + +// Describes the set of addresses for a network. +type NetworkAddresses struct { + // The contract address of RocketStorage + Storage string `yaml:"storage"` + // The contract address of the RPL token + RplToken string `yaml:"rplToken"` + // The contract address of the RPL faucet + RplFaucet string `yaml:"rplFaucet"` + // The contract address for Snapshot delegation + SnapshotDelegation string `yaml:"snapshotDelegation"` + // The contract address of rETH + Reth string `yaml:"reth"` + // The contract address of rocketRewardsPool from v1.0.0 + V1_0_0_RewardsPool string `yaml:"v1_0_0_RewardsPool"` + // The contract address of rocketClaimNode from v1.0.0 + V1_0_0_ClaimNode string `yaml:"v1_0_0_ClaimNode"` + // The contract address of rocketClaimTrustedNode from v1.0.0 + V1_0_0_ClaimTrustedNode string `yaml:"v1_0_0_ClaimTrustedNode"` + // The contract address of rocketMinipoolManager from v1.0.0 + V1_0_0_MinipoolManager string `yaml:"v1_0_0_MinipoolManager"` + // The contract address of rocketNetworkPrices from v1.1.0 + V1_1_0_NetworkPrices string `yaml:"v1_1_0_NetworkPrices"` + // The contract address of rocketNodeStaking from v1.1.0 + V1_1_0_NodeStaking string `yaml:"v1_1_0_NodeStaking"` + // The contract address of rocketNodeDeposit from v1.1.0 + V1_1_0_NodeDeposit string `yaml:"v1_1_0_NodeDeposit"` + // The contract address of rocketMinipoolQueue from v1.1.0 + V1_1_0_MinipoolQueue string `yaml:"v1_1_0_MinipoolQueue"` + // The contract address of rocketMinipoolFactory from v1.1.0 + V1_1_0_MinipoolFactory string `yaml:"v1_1_0_MinipoolFactory"` + // Addresses for RocketRewardsPool that have been upgraded during development + PreviousRewardsPools []string `yaml:"previousRewardsPools"` + // The RocketOvmPriceMessenger Optimism address for each network + OptimismPriceMessenger string `yaml:"optimismPriceMessenger"` + // The RocketPolygonPriceMessenger Polygon address for each network + PolygonPriceMessenger string `yaml:"polygonPriceMessenger"` + // The RocketArbitumPriceMessenger Arbitrum address for each network + ArbitrumPriceMessenger string `yaml:"arbitrumPriceMessenger"` + // The RocketArbitumPriceMessengerV2 Arbitrum address for each network + ArbitrumPriceMessengerV2 string `yaml:"arbitrumPriceMessengerV2"` + // The RocketZkSyncPriceMessenger zkSyncEra address for each network + ZkSyncEraPriceMessenger string `yaml:"zkSyncEraPriceMessenger"` + // The RocketBasePriceMessenger Base address for each network + BasePriceMessenger string `yaml:"basePriceMessenger"` + // The RocketScrollPriceMessenger Scroll address for each network + ScrollPriceMessenger string `yaml:"scrollPriceMessenger"` + // The Scroll L2 message fee estimator address for each network + ScrollFeeEstimator string `yaml:"scrollFeeEstimator"` + // The UniswapV3 pool address for each network (used for RPL price TWAP info) + RplTwapPool string `yaml:"rplTwapPool"` + // The multicall contract address + Multicall string `yaml:"multicall"` + // The BalanceChecker contract address + Balancebatcher string `yaml:"balancebatcher"` +}