From 7604065e07d8a68491f5f056e369cf8f9c5e6add Mon Sep 17 00:00:00 2001 From: lizekun Date: Wed, 26 Sep 2018 11:10:16 +0800 Subject: [PATCH 01/16] add geth proxy --- client.go | 6 +++--- geth.go | 15 +++++++++++++++ response.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 geth.go diff --git a/client.go b/client.go index e7422cd..878bdf1 100644 --- a/client.go +++ b/client.go @@ -68,7 +68,7 @@ func (c *Client) call(module, action string, param map[string]interface{}, outco err = fmt.Errorf("[ouch! panic recovered] please report this with what you did and what you expected, panic detail: %v", r) } }() - + fmt.Println(c.craftURL(module, action, param)) req, err := http.NewRequest(http.MethodGet, c.craftURL(module, action, param), http.NoBody) if err != nil { err = wrapErr(err, "http.NewRequest") @@ -129,8 +129,8 @@ func (c *Client) call(module, action string, param map[string]interface{}, outco err = wrapErr(err, "json unmarshal envelope") return } - if envelope.Status != 1 { - err = fmt.Errorf("etherscan server: %s", envelope.Message) + if envelope.Error.Code != 0 { + err = fmt.Errorf("etherscan server: %s", envelope.Error.Message) return } diff --git a/geth.go b/geth.go new file mode 100644 index 0000000..b7df5e6 --- /dev/null +++ b/geth.go @@ -0,0 +1,15 @@ +package etherscan + +import ( + "strconv" +) + +func (c *Client) GetBlockByNumber(blockNum int64) (block Block, err error) { + param := M{ + "boolean": "true", + "tag": strconv.FormatInt(blockNum, 16), + } + + err = c.call("proxy", "eth_getBlockByNumber", param, &block) + return +} diff --git a/response.go b/response.go index b1338d3..1ac4acc 100644 --- a/response.go +++ b/response.go @@ -7,16 +7,57 @@ package etherscan -import "encoding/json" +import ( + "encoding/json" +) // Envelope is the carrier of nearly every response type Envelope struct { - // 1 for good, 0 for error - Status int `json:"status,string"` - // OK for good, other words when Status equals 0 - Message string `json:"message"` - // where response lies Result json.RawMessage `json:"result"` + Error struct { + Code int `json:"code"` + Message string `json:"message"` + } +} + +type Transaction struct { + BlockHash string `json:"blockHash"` + BlockNumber string `json:"blockNumber"` + From string `json:"from"` + Gas string `json:"gas"` + GasPrice string `json:"gasPrice"` + Hash string `json:"hash"` + Input string `json:"input"` + Nonce string `json:"nonce"` + To string `json:"to"` + TransactionIndex string `json:"transactionIndex"` + Value string `json:"value"` + V string `json:"v"` + R string `json:"r"` + S string `json:"s"` +} + +type Block struct { + Difficulty string `json:"difficulty"` + ExtraData string `json:"extraData"` + GasLimit string `json:"gasLimit"` + GasUsed string `json:"gasUsed"` + Hash string `json:"hash"` + LogsBloom string `json:"logsBloom"` + Miner string `json:"miner"` + MixHash string `json:"mixHash"` + Nonce string `json:"nonce"` + Number string `json:"number"` + ParentHash string `json:"parentHash"` + ReceiptsRoot string `json:"receiptsRoot"` + Sha3Uncles string `json:"sha3Uncles"` + Size string `json:"size"` + StateRoot string `json:"stateRoot"` + Timestamp string `json:"timestamp"` + TotalDifficulty string `json:"totalDifficulty"` + Transactions []Transaction `json:"transactions"` + TransactionsRoot string `json:"transactionsRoot"` + Uncles []interface{} `json:"uncles"` } // AccountBalance account and its balance in pair From 4160acb0326aedfe78c73c983efe990429e86fd9 Mon Sep 17 00:00:00 2001 From: lizekun Date: Wed, 26 Sep 2018 11:16:00 +0800 Subject: [PATCH 02/16] remove print call url --- client.go | 1 - 1 file changed, 1 deletion(-) diff --git a/client.go b/client.go index 878bdf1..ce67da3 100644 --- a/client.go +++ b/client.go @@ -68,7 +68,6 @@ func (c *Client) call(module, action string, param map[string]interface{}, outco err = fmt.Errorf("[ouch! panic recovered] please report this with what you did and what you expected, panic detail: %v", r) } }() - fmt.Println(c.craftURL(module, action, param)) req, err := http.NewRequest(http.MethodGet, c.craftURL(module, action, param), http.NoBody) if err != nil { err = wrapErr(err, "http.NewRequest") From bbf3e49539acb4ee49980dd24df0aa998df93570 Mon Sep 17 00:00:00 2001 From: lizekun Date: Wed, 26 Sep 2018 11:19:47 +0800 Subject: [PATCH 03/16] remove print call url --- client.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client.go b/client.go index ce67da3..030f26a 100644 --- a/client.go +++ b/client.go @@ -132,6 +132,10 @@ func (c *Client) call(module, action string, param map[string]interface{}, outco err = fmt.Errorf("etherscan server: %s", envelope.Error.Message) return } + if envelope.Result == nil { + err = fmt.Errorf("null result") + return + } err = json.Unmarshal(envelope.Result, outcome) if err != nil { From 073631c9fb73f5ad18959f4752fa02c277494cdb Mon Sep 17 00:00:00 2001 From: lizekun Date: Wed, 26 Sep 2018 11:23:16 +0800 Subject: [PATCH 04/16] remove print call url --- client.go | 1 + 1 file changed, 1 insertion(+) diff --git a/client.go b/client.go index 030f26a..273c89e 100644 --- a/client.go +++ b/client.go @@ -132,6 +132,7 @@ func (c *Client) call(module, action string, param map[string]interface{}, outco err = fmt.Errorf("etherscan server: %s", envelope.Error.Message) return } + fmt.Println(envelope.Result) if envelope.Result == nil { err = fmt.Errorf("null result") return From bb61d3f3fab954ab920fd60994ae41f88d3931b8 Mon Sep 17 00:00:00 2001 From: lizekun Date: Wed, 26 Sep 2018 11:27:12 +0800 Subject: [PATCH 05/16] remove print call url --- client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client.go b/client.go index 273c89e..e25e3dc 100644 --- a/client.go +++ b/client.go @@ -133,7 +133,7 @@ func (c *Client) call(module, action string, param map[string]interface{}, outco return } fmt.Println(envelope.Result) - if envelope.Result == nil { + if string(envelope.Result) == "null" { err = fmt.Errorf("null result") return } From 9c37eea17222f8cbc760b1364435006b82356c9f Mon Sep 17 00:00:00 2001 From: lizekun Date: Wed, 26 Sep 2018 11:28:12 +0800 Subject: [PATCH 06/16] check null result --- client.go | 1 - 1 file changed, 1 deletion(-) diff --git a/client.go b/client.go index e25e3dc..23eddde 100644 --- a/client.go +++ b/client.go @@ -132,7 +132,6 @@ func (c *Client) call(module, action string, param map[string]interface{}, outco err = fmt.Errorf("etherscan server: %s", envelope.Error.Message) return } - fmt.Println(envelope.Result) if string(envelope.Result) == "null" { err = fmt.Errorf("null result") return From 90503079357ec9cbb61872449210ad05e6bdd790 Mon Sep 17 00:00:00 2001 From: lizekun Date: Wed, 26 Sep 2018 12:03:30 +0800 Subject: [PATCH 07/16] check null result --- geth.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/geth.go b/geth.go index b7df5e6..73a9e6f 100644 --- a/geth.go +++ b/geth.go @@ -1,6 +1,7 @@ package etherscan import ( + "math/big" "strconv" ) @@ -13,3 +14,9 @@ func (c *Client) GetBlockByNumber(blockNum int64) (block Block, err error) { err = c.call("proxy", "eth_getBlockByNumber", param, &block) return } + +func (c *Client) GasPrice() (price *big.Int, err error) { + param := M{} + err = c.call("proxy", "eth_gasPrice", param, price) + return +} From 5dd7cd64d6138e91fa0e4a32210665e8397bd924 Mon Sep 17 00:00:00 2001 From: lizekun Date: Wed, 26 Sep 2018 14:01:56 +0800 Subject: [PATCH 08/16] check null result --- geth.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/geth.go b/geth.go index 73a9e6f..6c712b7 100644 --- a/geth.go +++ b/geth.go @@ -20,3 +20,14 @@ func (c *Client) GasPrice() (price *big.Int, err error) { err = c.call("proxy", "eth_gasPrice", param, price) return } + +func (c *Client) EstimateGas(from, to string, value, gasPrice *big.Int) (limit uint64, err error) { + param := M{ + "value": value.Text(16), + "to": to, + "form": from, + "gasPrice": gasPrice.Text(16), + } + err = c.call("proxy", "eth_estimateGas", param, &limit) + return +} From 9c2c165f0b0ddf3514164661db86368b3d67bfbf Mon Sep 17 00:00:00 2001 From: lizekun Date: Wed, 26 Sep 2018 14:23:43 +0800 Subject: [PATCH 09/16] sendRawTransaction --- client.go | 2 ++ geth.go | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/client.go b/client.go index 23eddde..0a9b06a 100644 --- a/client.go +++ b/client.go @@ -68,11 +68,13 @@ func (c *Client) call(module, action string, param map[string]interface{}, outco err = fmt.Errorf("[ouch! panic recovered] please report this with what you did and what you expected, panic detail: %v", r) } }() + req, err := http.NewRequest(http.MethodGet, c.craftURL(module, action, param), http.NoBody) if err != nil { err = wrapErr(err, "http.NewRequest") return } + req.Header.Set("User-Agent", "etherscan-api(Go)") req.Header.Set("Content-Type", "application/json; charset=utf-8") diff --git a/geth.go b/geth.go index 6c712b7..84198dd 100644 --- a/geth.go +++ b/geth.go @@ -31,3 +31,11 @@ func (c *Client) EstimateGas(from, to string, value, gasPrice *big.Int) (limit u err = c.call("proxy", "eth_estimateGas", param, &limit) return } + +func (c *Client) SendRawTransaction(hex string) (hash string, err error) { + param := M{ + "hex": hex, + } + err = c.call("proxy", "eth_sendRawTransaction", param, &hash) + return +} From 5dc194d4e3cffcb994bf14f7a1c17fb0a1524c55 Mon Sep 17 00:00:00 2001 From: lizekun Date: Wed, 26 Sep 2018 14:26:20 +0800 Subject: [PATCH 10/16] sendRawTransaction --- geth.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geth.go b/geth.go index 84198dd..7347f7e 100644 --- a/geth.go +++ b/geth.go @@ -15,7 +15,7 @@ func (c *Client) GetBlockByNumber(blockNum int64) (block Block, err error) { return } -func (c *Client) GasPrice() (price *big.Int, err error) { +func (c *Client) GasPrice() (price *BigInt, err error) { param := M{} err = c.call("proxy", "eth_gasPrice", param, price) return From d6bd20bb9cd97034832c115a348789148898923c Mon Sep 17 00:00:00 2001 From: lizekun Date: Wed, 26 Sep 2018 14:36:16 +0800 Subject: [PATCH 11/16] sendRawTransaction --- geth.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/geth.go b/geth.go index 7347f7e..056d291 100644 --- a/geth.go +++ b/geth.go @@ -1,6 +1,7 @@ package etherscan import ( + "github.com/ethereum/go-ethereum/common/math" "math/big" "strconv" ) @@ -15,9 +16,11 @@ func (c *Client) GetBlockByNumber(blockNum int64) (block Block, err error) { return } -func (c *Client) GasPrice() (price *BigInt, err error) { +func (c *Client) GasPrice() (price *big.Int, err error) { param := M{} - err = c.call("proxy", "eth_gasPrice", param, price) + result := "" + err = c.call("proxy", "eth_gasPrice", param, &result) + price, _ = math.ParseBig256(result) return } From d88e992c6faafe4eb431d0caff09bf5d6ce29f90 Mon Sep 17 00:00:00 2001 From: lizekun Date: Wed, 26 Sep 2018 14:46:09 +0800 Subject: [PATCH 12/16] sendRawTransaction --- geth.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/geth.go b/geth.go index 056d291..95a89ee 100644 --- a/geth.go +++ b/geth.go @@ -31,7 +31,9 @@ func (c *Client) EstimateGas(from, to string, value, gasPrice *big.Int) (limit u "form": from, "gasPrice": gasPrice.Text(16), } - err = c.call("proxy", "eth_estimateGas", param, &limit) + limitStr := "" + err = c.call("proxy", "eth_estimateGas", param, &limitStr) + limit, err = strconv.ParseUint(limitStr, 16, 64) return } From 09acbd23fe2aafe6e58c9e177332c8c3df65843a Mon Sep 17 00:00:00 2001 From: lizekun Date: Wed, 26 Sep 2018 14:52:29 +0800 Subject: [PATCH 13/16] sendRawTransaction --- geth.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geth.go b/geth.go index 95a89ee..a449847 100644 --- a/geth.go +++ b/geth.go @@ -33,7 +33,7 @@ func (c *Client) EstimateGas(from, to string, value, gasPrice *big.Int) (limit u } limitStr := "" err = c.call("proxy", "eth_estimateGas", param, &limitStr) - limit, err = strconv.ParseUint(limitStr, 16, 64) + limit, err = strconv.ParseUint(limitStr, 0, 0) return } From 67e68c88566bbaf6b2cb2a21deaf9de93f6c9e21 Mon Sep 17 00:00:00 2001 From: lizekun Date: Thu, 27 Sep 2018 10:49:32 +0800 Subject: [PATCH 14/16] sendRawTransaction --- geth.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/geth.go b/geth.go index a449847..fb288ae 100644 --- a/geth.go +++ b/geth.go @@ -6,6 +6,15 @@ import ( "strconv" ) +func (c *Client) GetTransactionCount(address string) (count uint64, err error) { + param := M{ + "address": address, + "tag": "latest", + } + err = c.call("proxy", "eth_getTransactionCount", param, &count) + return +} + func (c *Client) GetBlockByNumber(blockNum int64) (block Block, err error) { param := M{ "boolean": "true", From cba77cbb620c0eea8bac60e0e409a611708cba4d Mon Sep 17 00:00:00 2001 From: lizekun Date: Thu, 27 Sep 2018 10:59:37 +0800 Subject: [PATCH 15/16] sendRawTransaction --- geth.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/geth.go b/geth.go index fb288ae..174115d 100644 --- a/geth.go +++ b/geth.go @@ -11,7 +11,9 @@ func (c *Client) GetTransactionCount(address string) (count uint64, err error) { "address": address, "tag": "latest", } - err = c.call("proxy", "eth_getTransactionCount", param, &count) + var countString string + err = c.call("proxy", "eth_getTransactionCount", param, &countString) + count, err = strconv.ParseUint(countString, 0, 0) return } From 10a1a679fd87e983c7ff846b7ce42b53135a721d Mon Sep 17 00:00:00 2001 From: lizekun Date: Thu, 27 Sep 2018 11:45:44 +0800 Subject: [PATCH 16/16] sendRawTransaction --- geth.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/geth.go b/geth.go index 174115d..9e27bda 100644 --- a/geth.go +++ b/geth.go @@ -35,12 +35,13 @@ func (c *Client) GasPrice() (price *big.Int, err error) { return } -func (c *Client) EstimateGas(from, to string, value, gasPrice *big.Int) (limit uint64, err error) { +func (c *Client) EstimateGas(from, to string, value, gasPrice *big.Int, data []byte) (limit uint64, err error) { param := M{ "value": value.Text(16), "to": to, "form": from, "gasPrice": gasPrice.Text(16), + "data": string(data), } limitStr := "" err = c.call("proxy", "eth_estimateGas", param, &limitStr)