Skip to content

Commit 55f4a93

Browse files
committed
[dev] client call is now okay
1 parent f552dcf commit 55f4a93

File tree

3 files changed

+106
-6
lines changed

3 files changed

+106
-6
lines changed

client.go

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"fmt"
1414
"io"
1515
"net/http"
16+
"net/http/httputil"
1617
"net/url"
1718
)
1819

@@ -49,14 +50,41 @@ func New(network Network, APIKey string) *Client {
4950

5051
// call does almost all the dirty work.
5152
func (c *Client) call(module, action string, param map[string]interface{}, outcome interface{}) (err error) {
52-
// todo: fire hooks
53-
// todo: verbose mode
53+
// fire hooks if in need
54+
if c.BeforeRequest != nil {
55+
err = c.BeforeRequest(module, action, param)
56+
if err != nil {
57+
err = wrapErr(err, "beforeRequest")
58+
return
59+
}
60+
}
61+
if c.AfterRequest != nil {
62+
defer c.AfterRequest(module, action, param, outcome, err)
63+
}
5464

55-
req, err := http.NewRequest(http.MethodGet, c.craftURL(param), http.NoBody)
65+
req, err := http.NewRequest(http.MethodGet, c.craftURL(module, action, param), http.NoBody)
5666
if err != nil {
5767
err = wrapErr(err, "http.NewRequest")
5868
return
5969
}
70+
req.Header.Set("User-Agent", "etherscan-api(Go)")
71+
72+
if c.Verbose {
73+
var reqDump []byte
74+
reqDump, err = httputil.DumpRequestOut(req, false)
75+
if err != nil {
76+
err = wrapErr(err, "verbose mode req dump failed")
77+
return
78+
}
79+
80+
fmt.Printf("\n%s\n", reqDump)
81+
82+
defer func() {
83+
if err != nil {
84+
fmt.Printf("[Error] %v\n", err)
85+
}
86+
}()
87+
}
6088

6189
res, err := c.coon.Do(req)
6290
if err != nil {
@@ -65,6 +93,17 @@ func (c *Client) call(module, action string, param map[string]interface{}, outco
6593
}
6694
defer res.Body.Close()
6795

96+
if c.Verbose {
97+
var resDump []byte
98+
resDump, err = httputil.DumpResponse(res, true)
99+
if err != nil {
100+
err = wrapErr(err, "verbose mode res dump failed")
101+
return
102+
}
103+
104+
fmt.Printf("%s\n", resDump)
105+
}
106+
68107
var content bytes.Buffer
69108
if _, err = io.Copy(&content, res.Body); err != nil {
70109
err = wrapErr(err, "reading response")
@@ -76,18 +115,31 @@ func (c *Client) call(module, action string, param map[string]interface{}, outco
76115
return
77116
}
78117

79-
err = json.Unmarshal(content.Bytes(), outcome)
118+
var envelope Envelope
119+
err = json.Unmarshal(content.Bytes(), &envelope)
120+
if err != nil {
121+
err = wrapErr(err, "json unmarshal envelope")
122+
return
123+
}
124+
if envelope.Status != 1 {
125+
err = fmt.Errorf("etherscan server: %s", envelope.Message)
126+
return
127+
}
128+
129+
err = json.Unmarshal(envelope.Result, outcome)
80130
if err != nil {
81-
err = wrapErr(err, "json unmarshal")
131+
err = wrapErr(err, "json unmarshal outcome")
82132
return
83133
}
84134

85135
return
86136
}
87137

88138
// craftURL returns desired URL via param provided
89-
func (c *Client) craftURL(param map[string]interface{}) (URL string) {
139+
func (c *Client) craftURL(module, action string, param map[string]interface{}) (URL string) {
90140
q := url.Values{
141+
"module": []string{module},
142+
"action": []string{action},
91143
"apikey": []string{c.key},
92144
}
93145

client_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) 2018 LI Zhennan
3+
*
4+
* Use of this work is governed by a MIT License.
5+
* You may find a license copy in project root.
6+
*/
7+
8+
package etherscan
9+
10+
import (
11+
"testing"
12+
)
13+
14+
func TestClient_craftURL(t *testing.T) {
15+
c := New(Ropsten, "abc123")
16+
17+
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`
18+
output := c.craftURL("testing", "craftURL", M{
19+
"one": 1,
20+
"two": "2",
21+
"three": []int{1, 2, 3},
22+
"four": []string{"d", "e", "f"},
23+
})
24+
25+
if output != expected {
26+
t.Fatalf("output != expected, got %s, want %s", output, expected)
27+
}
28+
}

response.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright (c) 2018 LI Zhennan
3+
*
4+
* Use of this work is governed by a MIT License.
5+
* You may find a license copy in project root.
6+
*/
7+
8+
package etherscan
9+
10+
import "encoding/json"
11+
12+
// Envelope is the carrier of nearly every response
13+
type Envelope struct {
14+
// 1 for good, 0 for error
15+
Status int `json:"status,string"`
16+
// OK for good, other words when Status equals 0
17+
Message string `json:"message"`
18+
// where response lies
19+
Result json.RawMessage `json:"result"`
20+
}

0 commit comments

Comments
 (0)