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