feat(network)_: implement (de)activable networks

This commit is contained in:
Dario Gabriel Lipicar 2025-01-31 11:25:24 -03:00 committed by dlipicar
parent 115fe9f73b
commit c862b563c0
11 changed files with 283 additions and 57 deletions

View File

@ -92,6 +92,8 @@ func mainnet(proxyHost, stageName string) params.Network {
Layer: 1,
Enabled: true,
RelatedChainID: SepoliaChainID,
IsActive: true,
IsDeactivatable: false,
}
}
@ -114,10 +116,10 @@ func sepolia(proxyHost, stageName string) params.Network {
return params.Network{
ChainID: chainID,
ChainName: "Mainnet",
ChainName: "Sepolia",
RpcProviders: rpcProviders,
BlockExplorerURL: "https://sepolia.etherscan.io/",
IconURL: "network/Network=Ethereum",
IconURL: "network/Network=Ethereum-test",
ChainColor: "#627EEA",
ShortName: "eth",
NativeCurrencyName: "Ether",
@ -127,6 +129,8 @@ func sepolia(proxyHost, stageName string) params.Network {
Layer: 1,
Enabled: true,
RelatedChainID: MainnetChainID,
IsActive: true,
IsDeactivatable: false,
}
}
@ -162,6 +166,8 @@ func optimism(proxyHost, stageName string) params.Network {
Layer: 2,
Enabled: true,
RelatedChainID: OptimismSepoliaChainID,
IsActive: true,
IsDeactivatable: true,
}
}
@ -184,10 +190,10 @@ func optimismSepolia(proxyHost, stageName string) params.Network {
return params.Network{
ChainID: chainID,
ChainName: "Optimism",
ChainName: "Optimism Sepolia",
RpcProviders: rpcProviders,
BlockExplorerURL: "https://sepolia-optimism.etherscan.io/",
IconURL: "network/Network=Optimism",
IconURL: "network/Network=Optimism-test",
ChainColor: "#E90101",
ShortName: "oeth",
NativeCurrencyName: "Ether",
@ -197,6 +203,8 @@ func optimismSepolia(proxyHost, stageName string) params.Network {
Layer: 2,
Enabled: false,
RelatedChainID: OptimismChainID,
IsActive: true,
IsDeactivatable: true,
}
}
@ -232,6 +240,8 @@ func arbitrum(proxyHost, stageName string) params.Network {
Layer: 2,
Enabled: true,
RelatedChainID: ArbitrumSepoliaChainID,
IsActive: true,
IsDeactivatable: true,
}
}
@ -254,10 +264,10 @@ func arbitrumSepolia(proxyHost, stageName string) params.Network {
return params.Network{
ChainID: chainID,
ChainName: "Arbitrum",
ChainName: "Arbitrum Sepolia",
RpcProviders: rpcProviders,
BlockExplorerURL: "https://sepolia-explorer.arbitrum.io/",
IconURL: "network/Network=Arbitrum",
IconURL: "network/Network=Arbitrum-test",
ChainColor: "#51D0F0",
ShortName: "arb1",
NativeCurrencyName: "Ether",
@ -267,6 +277,8 @@ func arbitrumSepolia(proxyHost, stageName string) params.Network {
Layer: 2,
Enabled: false,
RelatedChainID: ArbitrumChainID,
IsActive: true,
IsDeactivatable: true,
}
}
@ -302,6 +314,8 @@ func base(proxyHost, stageName string) params.Network {
Layer: 2,
Enabled: true,
RelatedChainID: BaseSepoliaChainID,
IsActive: true,
IsDeactivatable: true,
}
}
@ -324,10 +338,10 @@ func baseSepolia(proxyHost, stageName string) params.Network {
return params.Network{
ChainID: chainID,
ChainName: "Base",
ChainName: "Base Sepolia",
RpcProviders: rpcProviders,
BlockExplorerURL: "https://sepolia.basescan.org/",
IconURL: "network/Network=Base",
IconURL: "network/Network=Base-test",
ChainColor: "#0052FF",
ShortName: "base",
NativeCurrencyName: "Ether",
@ -337,6 +351,8 @@ func baseSepolia(proxyHost, stageName string) params.Network {
Layer: 2,
Enabled: false,
RelatedChainID: BaseChainID,
IsActive: true,
IsDeactivatable: true,
}
}

View File

@ -0,0 +1 @@
ALTER TABLE networks ADD COLUMN is_active BOOLEAN DEFAULT true;

View File

@ -0,0 +1 @@
ALTER TABLE networks ADD COLUMN is_deactivatable BOOLEAN DEFAULT true;

View File

@ -81,6 +81,8 @@ type Network struct {
ShortName string `json:"shortName" validate:"omitempty,min=1"`
TokenOverrides []TokenOverride `json:"tokenOverrides" validate:"omitempty,dive"`
RelatedChainID uint64 `json:"relatedChainId" validate:"omitempty"`
IsActive bool `json:"isActive"`
IsDeactivatable bool `json:"isDeactivatable"`
}
func (n *Network) DeepCopy() Network {

View File

@ -31,6 +31,7 @@ type NetworksPersistenceInterface interface {
DeleteAllNetworks() error
GetRpcPersistence() RpcProvidersPersistenceInterface
SetActive(chainID uint64, active bool) error
SetEnabled(chainID uint64, enabled bool) error
}
@ -60,7 +61,7 @@ func (n *NetworksPersistence) getNetworksWithoutProviders(onlyEnabled bool, chai
q := sq.Select(
"chain_id", "chain_name", "rpc_url", "fallback_url",
"block_explorer_url", "icon_url", "native_currency_name", "native_currency_symbol", "native_currency_decimals",
"is_test", "layer", "enabled", "chain_color", "short_name", "related_chain_id",
"is_test", "layer", "enabled", "chain_color", "short_name", "related_chain_id", "is_active", "is_deactivatable",
).
From("networks").
OrderBy("chain_id ASC")
@ -90,7 +91,7 @@ func (n *NetworksPersistence) getNetworksWithoutProviders(onlyEnabled bool, chai
&network.ChainID, &network.ChainName, &network.RPCURL, &network.FallbackURL,
&network.BlockExplorerURL, &network.IconURL, &network.NativeCurrencyName, &network.NativeCurrencySymbol,
&network.NativeCurrencyDecimals, &network.IsTest, &network.Layer, &network.Enabled, &network.ChainColor,
&network.ShortName, &relatedChainID,
&network.ShortName, &relatedChainID, &network.IsActive, &network.IsDeactivatable,
)
if err != nil {
return nil, err
@ -228,21 +229,21 @@ func (n *NetworksPersistence) upsertNetwork(network *params.Network) error {
Columns(
"chain_id", "chain_name", "rpc_url", "original_rpc_url", "fallback_url", "original_fallback_url",
"block_explorer_url", "icon_url", "native_currency_name", "native_currency_symbol", "native_currency_decimals",
"is_test", "layer", "enabled", "chain_color", "short_name", "related_chain_id",
"is_test", "layer", "enabled", "chain_color", "short_name", "related_chain_id", "is_active", "is_deactivatable",
).
Values(
network.ChainID, network.ChainName, network.RPCURL, network.OriginalRPCURL, network.FallbackURL, network.OriginalFallbackURL,
network.BlockExplorerURL, network.IconURL, network.NativeCurrencyName, network.NativeCurrencySymbol, network.NativeCurrencyDecimals,
network.IsTest, network.Layer, network.Enabled, network.ChainColor, network.ShortName, network.RelatedChainID,
network.IsTest, network.Layer, network.Enabled, network.ChainColor, network.ShortName, network.RelatedChainID, network.IsActive, network.IsDeactivatable,
).
Suffix("ON CONFLICT(chain_id) DO UPDATE SET " +
"chain_name = excluded.chain_name, rpc_url = excluded.rpc_url, original_rpc_url = excluded.original_rpc_url, " +
"fallback_url = excluded.fallback_url, original_fallback_url = excluded.original_fallback_url, " +
"block_explorer_url = excluded.block_explorer_url, icon_url = excluded.icon_url, " +
"native_currency_name = excluded.native_currency_name, native_currency_symbol = excluded.native_currency_symbol, " +
"native_currency_decimals = excluded.native_currency_decimals, is_test = excluded.is_test, " +
"layer = excluded.layer, enabled = excluded.enabled, chain_color = excluded.chain_color, " +
"short_name = excluded.short_name, related_chain_id = excluded.related_chain_id")
Suffix("ON CONFLICT(chain_id) DO UPDATE SET "+
"chain_name = excluded.chain_name, rpc_url = excluded.rpc_url, original_rpc_url = excluded.original_rpc_url, "+
"fallback_url = excluded.fallback_url, original_fallback_url = excluded.original_fallback_url, "+
"block_explorer_url = excluded.block_explorer_url, icon_url = excluded.icon_url, "+
"native_currency_name = excluded.native_currency_name, native_currency_symbol = excluded.native_currency_symbol, "+
"native_currency_decimals = excluded.native_currency_decimals, is_test = excluded.is_test, "+
"layer = excluded.layer, enabled = excluded.enabled, chain_color = excluded.chain_color, "+
"short_name = excluded.short_name, related_chain_id = excluded.related_chain_id, is_active = excluded.is_active", "is_deactivatable = excluded.is_deactivatable")
query, args, err := q.ToSql()
if err != nil {
@ -281,6 +282,25 @@ func (n *NetworksPersistence) DeleteNetwork(chainID uint64) error {
return nil
}
// SetActive updates the active status of a network.
func (n *NetworksPersistence) SetActive(chainID uint64, active bool) error {
q := sq.Update("networks").
Set("is_active", active).
Where(sq.Eq{"chain_id": chainID})
query, args, err := q.ToSql()
if err != nil {
return fmt.Errorf("failed to build update query: %w", err)
}
_, err = n.db.Exec(query, args...)
if err != nil {
return fmt.Errorf("failed to execute update query for chain_id %d: %w", chainID, err)
}
return nil
}
// SetEnabled updates the enabled status of a network.
func (n *NetworksPersistence) SetEnabled(chainID uint64, enabled bool) error {
q := sq.Update("networks").

View File

@ -196,6 +196,31 @@ func (s *NetworksPersistenceTestSuite) TestValidationForNetworksAndProviders() {
s.Require().Len(allNetworks, 0, "No invalid networks should be saved")
}
func (s *NetworksPersistenceTestSuite) TestSetActive() {
network := testutil.CreateNetwork(api.OptimismChainID, "Optimism Mainnet", DefaultProviders(api.OptimismChainID))
s.addAndVerifyNetworks([]*params.Network{network})
// Deactivate the network
err := s.networksPersistence.SetActive(network.ChainID, false)
s.Require().NoError(err)
// Verify the network is deactivated
updatedNetwork, err := s.networksPersistence.GetNetworkByChainID(network.ChainID)
s.Require().NoError(err)
s.Require().Len(updatedNetwork, 1)
s.Require().False(updatedNetwork[0].IsActive)
// Activate the network
err = s.networksPersistence.SetActive(network.ChainID, true)
s.Require().NoError(err)
// Verify the network is enabled
updatedNetwork, err = s.networksPersistence.GetNetworkByChainID(network.ChainID)
s.Require().NoError(err)
s.Require().Len(updatedNetwork, 1)
s.Require().True(updatedNetwork[0].IsActive)
}
func (s *NetworksPersistenceTestSuite) TestSetEnabled() {
network := testutil.CreateNetwork(api.OptimismChainID, "Optimism Mainnet", DefaultProviders(api.OptimismChainID))
s.addAndVerifyNetworks([]*params.Network{network})

12
rpc/network/errors.go Normal file
View File

@ -0,0 +1,12 @@
package network
import (
"github.com/status-im/status-go/errors"
)
// Abbreviation `NET` for the error code stands for Networks
var (
ErrNetworkNotDeactivatable = &errors.ErrorResponse{Code: errors.ErrorCode("NET-001"), Details: "network is not deactivatable"}
ErrActiveNetworksLimitReached = &errors.ErrorResponse{Code: errors.ErrorCode("NET-002"), Details: "maximum number of active networks reached"}
ErrUnsupportedChainId = &errors.ErrorResponse{Code: errors.ErrorCode("NET-003"), Details: "chainID is not supported"}
)

View File

@ -6,6 +6,7 @@ import (
"go.uber.org/zap"
"github.com/status-im/status-go/errors"
"github.com/status-im/status-go/logutils"
"github.com/status-im/status-go/multiaccounts/accounts"
"github.com/status-im/status-go/params"
@ -15,6 +16,9 @@ import (
)
//go:generate mockgen -package=mock -source=network.go -destination=mock/network.go
const MaxActiveNetworks = 5
type ManagerInterface interface {
InitEmbeddedNetworks(networks []params.Network) error
@ -30,6 +34,7 @@ type ManagerInterface interface {
GetTestNetworksEnabled() (bool, error)
SetUserRpcProviders(chainID uint64, providers []params.RpcProvider) error
SetActive(chainID uint64, active bool) error
SetEnabled(chainID uint64, enabled bool) error
}
@ -67,7 +72,7 @@ func NewManager(db *sql.DB) *Manager {
// Init initializes the nets, merges them with existing ones, and wraps the operation in a transaction.
// We should store the following information in the DB:
// - User's RPC providers
// - Enabled state of the network
// - Enabled and Active state of the network
// Embedded RPC providers should only be stored in memory
func (nm *Manager) InitEmbeddedNetworks(embeddedNetworks []params.Network) error {
if embeddedNetworks == nil {
@ -84,7 +89,7 @@ func (nm *Manager) InitEmbeddedNetworks(embeddedNetworks []params.Network) error
currentNetworks, err := txNetworksPersistence.GetAllNetworks()
if err != nil {
return fmt.Errorf("error fetching current networks: %w", err)
return errors.CreateErrorResponseFromError(fmt.Errorf("error fetching current networks: %w", err))
}
// Create a map for quick access to current networks
@ -93,12 +98,13 @@ func (nm *Manager) InitEmbeddedNetworks(embeddedNetworks []params.Network) error
currentNetworskMap[currentNetwork.ChainID] = *currentNetwork
}
// Keep user's rpc providers and enabled state
// Keep user's rpc providers, enabled and active state
var updatedNetworks []params.Network
for _, newNetwork := range embeddedNetworks {
if existingNetwork, exists := currentNetworskMap[newNetwork.ChainID]; exists {
newNetwork.RpcProviders = networkhelper.GetUserProviders(existingNetwork.RpcProviders)
newNetwork.Enabled = existingNetwork.Enabled
newNetwork.IsActive = existingNetwork.IsActive
} else {
newNetwork.RpcProviders = networkhelper.GetUserProviders(newNetwork.RpcProviders)
}
@ -108,32 +114,32 @@ func (nm *Manager) InitEmbeddedNetworks(embeddedNetworks []params.Network) error
// Use SetNetworks to replace all networks in the database without embedded RPC providers
err = txNetworksPersistence.SetNetworks(updatedNetworks)
if err != nil {
return fmt.Errorf("error setting networks: %w", err)
return errors.CreateErrorResponseFromError(fmt.Errorf("error setting networks: %w", err))
}
return nil
})
}
// GetEmbeddedProviders returns embedded providers for a given chainID.
func (nm *Manager) getEmbeddedProviders(chainID uint64) []params.RpcProvider {
func (nm *Manager) getEmbeddedNetwork(chainID uint64) *params.Network {
for _, network := range nm.embeddedNetworks {
if network.ChainID == chainID {
return networkhelper.GetEmbeddedProviders(network.RpcProviders)
return &network
}
}
return nil
}
// setEmbeddedProviders adds embedded providers to a network.
func (nm *Manager) setNetworkEmbeddedProviders(network *params.Network) {
network.RpcProviders = networkhelper.ReplaceEmbeddedProviders(
network.RpcProviders, nm.getEmbeddedProviders(network.ChainID))
}
func (nm *Manager) setEmbeddedProviders(networks []*params.Network) {
// Set fields that must be taken from embedded networks.
func (nm *Manager) setEmbeddedFields(networks []*params.Network) {
for _, network := range networks {
nm.setNetworkEmbeddedProviders(network)
embeddedNetwork := nm.getEmbeddedNetwork(network.ChainID)
if embeddedNetwork != nil {
network.IsDeactivatable = embeddedNetwork.IsDeactivatable
// Append embedded providers to the user providers
network.RpcProviders = networkhelper.ReplaceEmbeddedProviders(
network.RpcProviders, embeddedNetwork.RpcProviders)
}
}
}
@ -146,11 +152,15 @@ func (nm *Manager) networkWithoutEmbeddedProviders(network *params.Network) *par
// Upsert adds or updates a network, synchronizing RPC providers, wrapped in a transaction.
func (nm *Manager) Upsert(network *params.Network) error {
// New networks are deactivated by default. They are also always deactivatable.
network.IsActive = false
network.IsDeactivatable = true
return persistence.ExecuteWithinTransaction(nm.db, func(tx *sql.Tx) error {
txNetworksPersistence := persistence.NewNetworksPersistence(tx)
err := txNetworksPersistence.UpsertNetwork(nm.networkWithoutEmbeddedProviders(network))
if err != nil {
return fmt.Errorf("failed to upsert network: %w", err)
return errors.CreateErrorResponseFromError(fmt.Errorf("failed to upsert network: %w", err))
}
return nil
})
@ -162,7 +172,7 @@ func (nm *Manager) Delete(chainID uint64) error {
txNetworksPersistence := persistence.NewNetworksPersistence(tx)
err := txNetworksPersistence.DeleteNetwork(chainID)
if err != nil {
return fmt.Errorf("failed to delete network: %w", err)
return errors.CreateErrorResponseFromError(fmt.Errorf("failed to delete network: %w", err))
}
return nil
})
@ -174,11 +184,39 @@ func (nm *Manager) SetUserRpcProviders(chainID uint64, userProviders []params.Rp
return rpcPersistence.SetRpcProviders(chainID, networkhelper.GetUserProviders(userProviders))
}
// SetActive updates the active status of a network
func (nm *Manager) SetActive(chainID uint64, active bool) error {
network := nm.Find(chainID)
if network == nil {
return ErrUnsupportedChainId
}
// If trying to deactivate, check that it's deactivatable
if !active && !network.IsDeactivatable {
return ErrNetworkNotDeactivatable
}
// If trying to activate, check that we haven't reached the limit for the corresponding mode
activeNetworks, err := nm.getActiveNetworksForTestMode(network.IsTest)
if err != nil {
return errors.CreateErrorResponseFromError(fmt.Errorf("failed to get active networks: %w", err))
}
if active && len(activeNetworks) >= MaxActiveNetworks {
return ErrActiveNetworksLimitReached
}
err = nm.networkPersistence.SetActive(chainID, active)
if err != nil {
return errors.CreateErrorResponseFromError(fmt.Errorf("failed to persist active status: %w", err))
}
return nil
}
// SetEnabled updates the enabled status of a network
func (nm *Manager) SetEnabled(chainID uint64, enabled bool) error {
err := nm.networkPersistence.SetEnabled(chainID, enabled)
if err != nil {
return fmt.Errorf("failed to set enabled status: %w", err)
return errors.CreateErrorResponseFromError(fmt.Errorf("failed to set enabled status: %w", err))
}
return nil
}
@ -191,7 +229,7 @@ func (nm *Manager) Find(chainID uint64) *params.Network {
return nil
}
result := networks[0]
nm.setNetworkEmbeddedProviders(result)
nm.setEmbeddedFields([]*params.Network{result})
return result
}
@ -201,7 +239,7 @@ func (nm *Manager) GetAll() ([]*params.Network, error) {
if err != nil {
return nil, err
}
nm.setEmbeddedProviders(networks)
nm.setEmbeddedFields(networks)
return networks, nil
}
@ -211,7 +249,7 @@ func (nm *Manager) Get(onlyEnabled bool) ([]*params.Network, error) {
if err != nil {
return nil, err
}
nm.setEmbeddedProviders(networks)
nm.setEmbeddedFields(networks)
return networks, nil
}
@ -225,13 +263,7 @@ func (nm *Manager) GetTestNetworksEnabled() (result bool, err error) {
return nm.accountsDB.GetTestNetworksEnabled()
}
// GetActiveNetworks returns active networks based on the current mode (test/prod).
func (nm *Manager) GetActiveNetworks() ([]*params.Network, error) {
areTestNetworksEnabled, err := nm.GetTestNetworksEnabled()
if err != nil {
return nil, err
}
func (nm *Manager) getActiveNetworksForTestMode(areTestNetworksEnabled bool) ([]*params.Network, error) {
networks, err := nm.GetAll()
if err != nil {
return nil, err
@ -239,7 +271,7 @@ func (nm *Manager) GetActiveNetworks() ([]*params.Network, error) {
var availableNetworks []*params.Network
for _, network := range networks {
if network.IsTest == areTestNetworksEnabled {
if network.IsActive && network.IsTest == areTestNetworksEnabled {
availableNetworks = append(availableNetworks, network)
}
}
@ -247,6 +279,16 @@ func (nm *Manager) GetActiveNetworks() ([]*params.Network, error) {
return availableNetworks, nil
}
// GetActiveNetworks returns active networks based on the current mode (test/prod).
func (nm *Manager) GetActiveNetworks() ([]*params.Network, error) {
areTestNetworksEnabled, err := nm.GetTestNetworksEnabled()
if err != nil {
return nil, err
}
return nm.getActiveNetworksForTestMode(areTestNetworksEnabled)
}
func (nm *Manager) GetCombinedNetworks() ([]*CombinedNetwork, error) {
networks, err := nm.Get(false)
if err != nil {

View File

@ -44,7 +44,22 @@ func (s *NetworkManagerTestSuite) SetupTest() {
*testutil.CreateNetwork(api.OptimismChainID, "Optimistic Ethereum", []params.RpcProvider{
testutil.CreateProvider(api.OptimismChainID, "Infura Optimism", params.UserProviderType, true, "https://optimism.infura.io"),
}),
*testutil.CreateNetwork(api.OptimismSepoliaChainID, "Optimistic Sepolia", []params.RpcProvider{
testutil.CreateProvider(api.OptimismSepoliaChainID, "Infura Optimism Sepolia", params.UserProviderType, true, "https://optimism-sepolia.infura.io"),
}),
*testutil.CreateNetwork(api.BaseChainID, "Base", []params.RpcProvider{
testutil.CreateProvider(api.BaseChainID, "Infura Base", params.UserProviderType, true, "https://base.infura.io"),
}),
*testutil.CreateNetwork(api.BaseSepoliaChainID, "Base Sepolia", []params.RpcProvider{
testutil.CreateProvider(api.BaseSepoliaChainID, "Infura Base Sepolia", params.UserProviderType, true, "https://base-sepolia.infura.io"),
}),
}
// Make "Ethereum Mainnet" network not deactivatable
initNetworks[0].IsDeactivatable = false
// Make "Optimistic Ethereum" network inactive by default
initNetworks[2].IsActive = false
err = persistence.SetNetworks(initNetworks)
s.Require().NoError(err)
s.assertDbNetworks(initNetworks)
@ -259,10 +274,15 @@ func (s *NetworkManagerTestSuite) TestLegacyFieldPopulationWithoutUserProviders(
}
func (s *NetworkManagerTestSuite) TestUpsertNetwork() {
chainID := uint64(999)
// Create a new network
newNetwork := testutil.CreateNetwork(api.MainnetChainID, "Ethereum Mainnet", []params.RpcProvider{
testutil.CreateProvider(api.MainnetChainID, "Infura Mainnet", params.EmbeddedProxyProviderType, true, "https://mainnet.infura.io"),
newNetwork := testutil.CreateNetwork(chainID, "Ethereum Mainnet", []params.RpcProvider{
testutil.CreateProvider(chainID, "Infura Mainnet", params.EmbeddedProxyProviderType, true, "https://mainnet.infura.io"),
})
// Check that these values are overriden for upserted networks
newNetwork.IsActive = true
newNetwork.IsDeactivatable = false
// Upsert the network
err := s.manager.Upsert(newNetwork)
@ -270,9 +290,76 @@ func (s *NetworkManagerTestSuite) TestUpsertNetwork() {
// Verify the network was upserted without embedded providers
persistence := db.NewNetworksPersistence(s.db)
chainID := api.MainnetChainID
networks, err := persistence.GetNetworks(false, &chainID)
s.Require().NoError(err)
s.Require().Len(networks, 1)
s.Require().Len(networkhelper.GetEmbeddedProviders(networks[0].RpcProviders), 0)
s.Require().False(networks[0].IsActive)
s.Require().True(networks[0].IsDeactivatable)
}
func (s *NetworkManagerTestSuite) TestSetActive() {
var err error
var n *params.Network
// Check that the "Base" network is active by default
n = s.manager.Find(api.BaseChainID)
s.Require().NotNil(n)
s.True(n.IsActive)
// Set the "Base" network to inactive
err = s.manager.SetActive(api.BaseChainID, false)
s.Require().NoError(err)
// Verify the network was set to inactive
n = s.manager.Find(api.BaseChainID)
s.Require().NotNil(n)
s.False(n.IsActive)
// Set the "Base" network to active
err = s.manager.SetActive(api.BaseChainID, true)
s.Require().NoError(err)
// Verify the network was set to active
n = s.manager.Find(api.BaseChainID)
s.Require().NotNil(n)
s.True(n.IsActive)
}
func (s *NetworkManagerTestSuite) TestSetActiveNotDeactivatable() {
var err error
var n *params.Network
// Try to set Ethereum Mainnet to inactive (should fail)
err = s.manager.SetActive(api.MainnetChainID, false)
s.Require().Error(err)
// Verify the network was not set to inactive
n = s.manager.Find(api.MainnetChainID)
s.Require().NotNil(n)
s.True(n.IsActive)
}
func (s *NetworkManagerTestSuite) TestSetActiveMaxNumberOfActiveNetworks() {
var err error
var n *params.Network
// Check that we're at the limit of active networks
activeNetworks, err := s.manager.GetActiveNetworks()
s.Require().NoError(err)
s.Require().Len(activeNetworks, network.MaxActiveNetworks)
// Check that the "Optimistic Ethereum" network is inactive by default
n = s.manager.Find(api.OptimismChainID)
s.Require().NotNil(n)
s.False(n.IsActive)
// Try to set the "Optimistic Ethereum" network to active (should fail due to number networks active)
err = s.manager.SetActive(api.OptimismChainID, true)
s.Require().Error(err)
// Verify the network was not set to active
n = s.manager.Find(api.OptimismChainID)
s.Require().NotNil(n)
s.False(n.IsActive)
}

View File

@ -40,6 +40,8 @@ func CreateNetwork(chainID uint64, chainName string, providers []params.RpcProvi
ShortName: "eth",
RelatedChainID: api.OptimismSepoliaChainID,
RpcProviders: providers,
IsActive: true,
IsDeactivatable: true,
}
}
@ -71,6 +73,8 @@ func CompareNetworks(t require.TestingT, expected, actual *params.Network) {
require.Equal(t, expected.ChainColor, actual.ChainColor)
require.Equal(t, expected.ShortName, actual.ShortName)
require.Equal(t, expected.RelatedChainID, actual.RelatedChainID)
require.Equal(t, expected.IsActive, actual.IsActive)
require.Equal(t, expected.IsDeactivatable, actual.IsDeactivatable)
}
// Helper function to compare lists of providers

View File

@ -395,31 +395,47 @@ func (api *API) SearchCollections(ctx context.Context, chainID wcommon.ChainID,
Collectibles API End
*/
// @deprecated: Custom networks not currently supported. Change settings using specific API functions.
func (api *API) AddEthereumChain(ctx context.Context, network params.Network) error {
logutils.ZapLogger().Debug("call to AddEthereumChain")
return api.s.rpcClient.NetworkManager.Upsert(&network)
}
// @deprecated: Custom networks not currently supported. Change settings using specific API functions.
func (api *API) DeleteEthereumChain(ctx context.Context, chainID uint64) error {
logutils.ZapLogger().Debug("call to DeleteEthereumChain")
return api.s.rpcClient.NetworkManager.Delete(chainID)
}
func (api *API) SetChainUserRpcProviders(ctx context.Context, chainID uint64, rpcProviders []params.RpcProvider) error {
logutils.ZapLogger().Debug("call to SetChainUserRpcProviders")
return api.s.rpcClient.NetworkManager.SetUserRpcProviders(chainID, rpcProviders)
}
// Active chains are the ones that are available for selection across the whole application
// Providers are expected to be accessed only for active chains.
func (api *API) SetChainActive(ctx context.Context, chainID uint64, active bool) error {
logutils.ZapLogger().Debug("call to SetChainActive")
return api.s.rpcClient.NetworkManager.SetActive(chainID, active)
}
// Enabled chains are the ones taken into account when displaying balances, collectibles, activity, etc.
func (api *API) SetChainEnabled(ctx context.Context, chainID uint64, enabled bool) error {
logutils.ZapLogger().Debug("call to SetChainEnabled")
return api.s.rpcClient.NetworkManager.SetEnabled(chainID, enabled)
}
func (api *API) DeleteEthereumChain(ctx context.Context, chainID uint64) error {
logutils.ZapLogger().Debug("call to DeleteEthereumChain")
return api.s.rpcClient.NetworkManager.Delete(chainID)
}
// @deprecated: Combined networks are not used anymore, use GetFlatEthereumChains instead
func (api *API) GetEthereumChains(ctx context.Context) ([]*network.CombinedNetwork, error) {
logutils.ZapLogger().Debug("call to GetEthereumChains")
return api.s.rpcClient.NetworkManager.GetCombinedNetworks()
}
func (api *API) GetFlatEthereumChains(ctx context.Context) ([]*params.Network, error) {
logutils.ZapLogger().Debug("call to GetFlatEthereumChains")
return api.s.rpcClient.NetworkManager.GetAll()
}
// @deprecated
func (api *API) FetchPrices(ctx context.Context, symbols []string, currencies []string) (map[string]map[string]float64, error) {
logutils.ZapLogger().Debug("call to FetchPrices")