github.com/0xsequence/ethkit@v1.25.0/ethproviders/ethproviders.go (about)

     1  package ethproviders
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  
     7  	"github.com/0xsequence/ethkit/ethrpc"
     8  )
     9  
    10  type Providers struct {
    11  	byID          map[uint64]*ethrpc.Provider
    12  	byName        map[string]*ethrpc.Provider
    13  	configByID    map[uint64]NetworkConfig
    14  	authChain     *ethrpc.Provider
    15  	testAuthChain *ethrpc.Provider
    16  	chainList     []ChainInfo
    17  }
    18  
    19  type ChainInfo struct {
    20  	ID   uint64 `json:"id"` // TODO: switch to *big.Int
    21  	Name string `json:"name"`
    22  }
    23  
    24  func NewProviders(cfg Config, optJwtToken ...string) (*Providers, error) {
    25  	providers := &Providers{
    26  		byID:       map[uint64]*ethrpc.Provider{},
    27  		byName:     map[string]*ethrpc.Provider{},
    28  		configByID: map[uint64]NetworkConfig{},
    29  	}
    30  
    31  	var providerJwtAuth ethrpc.Option
    32  	if len(optJwtToken) > 0 && optJwtToken[0] != "" {
    33  		providerJwtAuth = ethrpc.WithJWTAuthorization(optJwtToken[0])
    34  	}
    35  
    36  	for name, details := range cfg {
    37  		if details.Disabled {
    38  			continue
    39  		}
    40  
    41  		p, err := ethrpc.NewProvider(details.URL, providerJwtAuth)
    42  		if err != nil {
    43  			return nil, err
    44  		}
    45  		providers.byID[details.ID] = p
    46  		providers.byName[name] = p
    47  		providers.configByID[details.ID] = details
    48  
    49  		if (details.AuthChain && !details.Testnet && providers.authChain != nil) || (details.AuthChain && details.Testnet && providers.testAuthChain != nil) {
    50  			return nil, fmt.Errorf("duplicate auth chain providers detected in config")
    51  		}
    52  		if details.AuthChain && !details.Testnet {
    53  			providers.authChain = p
    54  		}
    55  		if details.AuthChain && details.Testnet {
    56  			providers.testAuthChain = p
    57  		}
    58  	}
    59  	if len(providers.byID) != len(providers.byName) {
    60  		return nil, fmt.Errorf("duplicate provider id or name detected")
    61  	}
    62  
    63  	// also record the chain number as string for easier lookup
    64  	for k, p := range providers.byID {
    65  		providers.byName[fmt.Sprintf("%d", k)] = p
    66  	}
    67  
    68  	// build the chain list object
    69  	chainList := []ChainInfo{}
    70  	for name, networkConfig := range cfg {
    71  		if networkConfig.Disabled {
    72  			continue
    73  		}
    74  
    75  		chainList = append(chainList, ChainInfo{ID: networkConfig.ID, Name: name})
    76  	}
    77  	sort.SliceStable(chainList, func(i, j int) bool {
    78  		return chainList[i].ID < chainList[j].ID
    79  	})
    80  	providers.chainList = chainList
    81  
    82  	return providers, nil
    83  }
    84  
    85  // Get is a helper method which will allow you to fetch the provider for a chain by either
    86  // the chain canonical name, or by the chain canonical id. This works because at the time
    87  // of configuring the providers list in `NewProviders` we assign the name and string-id
    88  // to the byName mapping.
    89  func (p *Providers) Get(chainHandle string) *ethrpc.Provider {
    90  	return p.byName[chainHandle]
    91  }
    92  
    93  func (p *Providers) GetByChainID(chainID uint64) *ethrpc.Provider {
    94  	return p.byID[chainID]
    95  }
    96  
    97  func (p *Providers) GetByChainName(chainName string) *ethrpc.Provider {
    98  	return p.byName[chainName]
    99  }
   100  
   101  func (p *Providers) GetAuthChain() *ethrpc.Provider {
   102  	return p.authChain
   103  }
   104  
   105  func (p *Providers) GetTestAuthChain() *ethrpc.Provider {
   106  	return p.testAuthChain
   107  }
   108  
   109  func (p *Providers) GetAuthProvider() *ethrpc.Provider {
   110  	return p.authChain
   111  }
   112  
   113  func (p *Providers) GetTestnetAuthProvider() *ethrpc.Provider {
   114  	return p.testAuthChain
   115  }
   116  
   117  func (p *Providers) ProviderMap() map[uint64]*ethrpc.Provider {
   118  	return p.byID
   119  }
   120  
   121  func (p *Providers) LookupAuthProviderByChainID(chainID uint64) *ethrpc.Provider {
   122  	details, ok := p.configByID[chainID]
   123  	if !ok {
   124  		return nil
   125  	}
   126  	if details.Testnet {
   127  		return p.testAuthChain
   128  	} else {
   129  		return p.authChain
   130  	}
   131  }
   132  
   133  func (p *Providers) ChainList() []ChainInfo {
   134  	return p.chainList
   135  }
   136  
   137  func (p *Providers) FindChain(chainHandle string) (uint64, ChainInfo, error) {
   138  	for _, info := range p.chainList {
   139  		if chainHandle == info.Name || chainHandle == fmt.Sprintf("%d", info.ID) {
   140  			return info.ID, info, nil // found
   141  		}
   142  	}
   143  	return 0, ChainInfo{}, fmt.Errorf("chainID not found")
   144  }