@@ -15,15 +15,18 @@ import (
15
15
"net/http"
16
16
"net/http/httputil"
17
17
"net/url"
18
+ "sync"
18
19
"time"
19
20
)
20
21
21
22
// Client etherscan API client
22
23
// Clients are safe for concurrent use by multiple goroutines.
23
24
type Client struct {
24
- coon * http.Client
25
- key string
26
- baseURL string
25
+ coon * http.Client
26
+ baseURL string
27
+ keys []string
28
+ keySelectMutex sync.Mutex
29
+ keySelectIdx int
27
30
28
31
// Verbose when true, talks a lot
29
32
Verbose bool
@@ -37,12 +40,22 @@ type Client struct {
37
40
AfterRequest func (module , action string , param map [string ]interface {}, outcome interface {}, requestErr error )
38
41
}
39
42
43
+ func (c * Client ) getKey () string {
44
+ c .keySelectMutex .Lock ()
45
+ defer c .keySelectMutex .Unlock ()
46
+ c .keySelectIdx ++
47
+ if c .keySelectIdx >= len (c .keys ) {
48
+ c .keySelectIdx = 0
49
+ }
50
+ return c .keys [c .keySelectIdx ]
51
+ }
52
+
40
53
// New initialize a new etherscan API client
41
54
// please use pre-defined network value
42
- func New (network Network , APIKey string ) * Client {
55
+ func New (network Network , APIKeys [] string ) * Client {
43
56
return NewCustomized (Customization {
44
57
Timeout : 30 * time .Second ,
45
- Key : APIKey ,
58
+ Keys : APIKeys ,
46
59
BaseURL : fmt .Sprintf (`https://%s.etherscan.io/api?` , network .SubDomain ()),
47
60
})
48
61
}
@@ -51,8 +64,8 @@ func New(network Network, APIKey string) *Client {
51
64
type Customization struct {
52
65
// Timeout for API call
53
66
Timeout time.Duration
54
- // API key applied from Etherscan
55
- Key string
67
+ // API keys applied from Etherscan
68
+ Keys [] string
56
69
// Base URL like `https://api.etherscan.io/api?`
57
70
BaseURL string
58
71
// When true, talks a lot
@@ -83,7 +96,7 @@ func NewCustomized(config Customization) *Client {
83
96
}
84
97
return & Client {
85
98
coon : httpClient ,
86
- key : config .Key ,
99
+ keys : config .Keys ,
87
100
baseURL : config .BaseURL ,
88
101
Verbose : config .Verbose ,
89
102
BeforeRequest : config .BeforeRequest ,
@@ -117,7 +130,7 @@ func (c *Client) call(module, action string, param map[string]interface{}, outco
117
130
err = wrapErr (err , "http.NewRequest" )
118
131
return
119
132
}
120
- req .Header .Set ("User-Agent" , "etherscan-api(Go)" )
133
+ req .Header .Set ("User-Agent" , "etherscan-api-multikey (Go)" )
121
134
req .Header .Set ("Content-Type" , "application/json; charset=utf-8" )
122
135
123
136
if c .Verbose {
@@ -196,7 +209,7 @@ func (c *Client) craftURL(module, action string, param map[string]interface{}) (
196
209
q := url.Values {
197
210
"module" : []string {module },
198
211
"action" : []string {action },
199
- "apikey" : []string {c .key },
212
+ "apikey" : []string {c .getKey () },
200
213
}
201
214
202
215
for k , v := range param {
0 commit comments