Skip to content

Commit 72c4058

Browse files
committed
Added support for multiple keys
1 parent 07a1d97 commit 72c4058

File tree

3 files changed

+25
-12
lines changed

3 files changed

+25
-12
lines changed

client.go

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,18 @@ import (
1515
"net/http"
1616
"net/http/httputil"
1717
"net/url"
18+
"sync"
1819
"time"
1920
)
2021

2122
// Client etherscan API client
2223
// Clients are safe for concurrent use by multiple goroutines.
2324
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
2730

2831
// Verbose when true, talks a lot
2932
Verbose bool
@@ -37,12 +40,22 @@ type Client struct {
3740
AfterRequest func(module, action string, param map[string]interface{}, outcome interface{}, requestErr error)
3841
}
3942

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+
4053
// New initialize a new etherscan API client
4154
// please use pre-defined network value
42-
func New(network Network, APIKey string) *Client {
55+
func New(network Network, APIKeys []string) *Client {
4356
return NewCustomized(Customization{
4457
Timeout: 30 * time.Second,
45-
Key: APIKey,
58+
Keys: APIKeys,
4659
BaseURL: fmt.Sprintf(`https://%s.etherscan.io/api?`, network.SubDomain()),
4760
})
4861
}
@@ -51,8 +64,8 @@ func New(network Network, APIKey string) *Client {
5164
type Customization struct {
5265
// Timeout for API call
5366
Timeout time.Duration
54-
// API key applied from Etherscan
55-
Key string
67+
// API keys applied from Etherscan
68+
Keys []string
5669
// Base URL like `https://api.etherscan.io/api?`
5770
BaseURL string
5871
// When true, talks a lot
@@ -83,7 +96,7 @@ func NewCustomized(config Customization) *Client {
8396
}
8497
return &Client{
8598
coon: httpClient,
86-
key: config.Key,
99+
keys: config.Keys,
87100
baseURL: config.BaseURL,
88101
Verbose: config.Verbose,
89102
BeforeRequest: config.BeforeRequest,
@@ -117,7 +130,7 @@ func (c *Client) call(module, action string, param map[string]interface{}, outco
117130
err = wrapErr(err, "http.NewRequest")
118131
return
119132
}
120-
req.Header.Set("User-Agent", "etherscan-api(Go)")
133+
req.Header.Set("User-Agent", "etherscan-api-multikey(Go)")
121134
req.Header.Set("Content-Type", "application/json; charset=utf-8")
122135

123136
if c.Verbose {
@@ -196,7 +209,7 @@ func (c *Client) craftURL(module, action string, param map[string]interface{}) (
196209
q := url.Values{
197210
"module": []string{module},
198211
"action": []string{action},
199-
"apikey": []string{c.key},
212+
"apikey": []string{c.getKey()},
200213
}
201214

202215
for k, v := range param {

client_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
)
1313

1414
func TestClient_craftURL(t *testing.T) {
15-
c := New(Ropsten, "abc123")
15+
c := New(Ropsten, []string{"abc123"})
1616

1717
const expected = `https://api-ropsten.etherscan.io/api?action=craftURL&apikey=abc123&four=d&four=e&four=f&module=testing&one=1&three=1&three=2&three=3&two=2`
1818
output := c.craftURL("testing", "craftURL", M{

setup_e2e_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func init() {
3232
}
3333
bucket = NewBucket(500 * time.Millisecond)
3434

35-
api = New(Mainnet, apiKey)
35+
api = New(Mainnet, []string{apiKey})
3636
api.Verbose = true
3737
api.BeforeRequest = func(module string, action string, param map[string]interface{}) error {
3838
bucket.Take()

0 commit comments

Comments
 (0)