nanmu42 / etherscan-api

:guitar: Golang client for Ethereum Etherscan API (and its families like BscScan) / Golang 以太坊 Etherscan API库(也支持同一家族的BscScan)
MIT License
240 stars 107 forks source link

proxy methods not implemented #5

Closed BenKnigge closed 5 years ago

BenKnigge commented 6 years ago

I noticed that the proxy methods were not implemented and wouldn't mind contributing if you're open to a pull request.

These are what I'm referring to.

https://etherscan.io/apis#proxy

Is there anything else omitted that you're aware of?

nanmu42 commented 6 years ago

I would really appreciate that, however, there's already a good implement. :)

The proxy methods are actually a port on Geth/Parity RPC, where there are public APIs on Infura(https://infura.io) and go package ethclient(https://github.com/ethereum/go-ethereum/tree/master/ethclient).

Thanks for your kind mind. :D

BenKnigge commented 6 years ago

I'm currently using infura with github.com/onrik/ethrpc . I just thought that for the sake of completeness and simplicity it would be nice if those geth proxy methods that are supported by etherscan were implemented in this library. I'll add this to my long list of things to do.

nanmu42 commented 6 years ago

Well then I am looking forward to your PR. ;)

GlenDC commented 5 years ago

While working on a quick prototype for some project I was using your API @nanmu42. Thank you for the work you did, saved me a lot of time. I already support in my local version one proxy call, the one I needed.

The thing (first difference) I did notice is that the result for the Proxy calls does not match the Envelope structure, but is instead a JSON RPC 2.0 result. So not sure what you would do with that in your client code. For now I just manually mapped from one to the other structure, but I guess if this is to become an actual solution you would need to map it properly.

Here is the hack diff I did for now, to give some context and for those who are interested, with just enough work done so I could do my actual prototype:

diff --git a/client.go b/client.go
index b981d59..b632469 100644
--- a/client.go
+++ b/client.go
@@ -127,14 +127,34 @@ func (c *Client) call(module, action string, param map[string]interface{}, outco
    }

    var envelope Envelope
-   err = json.Unmarshal(content.Bytes(), &envelope)
-   if err != nil {
-       err = wrapErr(err, "json unmarshal envelope")
-       return
-   }
-   if envelope.Status != 1 {
-       err = fmt.Errorf("etherscan server: %s", envelope.Message)
-       return
+   if module == "proxy" {
+       var jsonRPCResp struct {
+           JSONRPC string          `json:"jsonrpc"`
+           ID      int             `json:"id"`
+           Result  json.RawMessage `json:"result"`
+       }
+       err = json.Unmarshal(content.Bytes(), &jsonRPCResp)
+       if err != nil {
+           err = wrapErr(err, "json unmarshal JSON RPC 2.0 resp")
+           return
+       }
+       // TODO: validate resp
+       // map to envelope
+       // TODO: does this mapping need to be improved?
+       envelope.Status = 1
+       envelope.Message = "OK"
+       envelope.Result = jsonRPCResp.Result
+   } else {
+       err = json.Unmarshal(content.Bytes(), &envelope)
+       if err != nil {
+           err = wrapErr(err, "json unmarshal envelope")
+           return
+       }
+       if envelope.Status != 1 {
+           fmt.Println("env. status", envelope.Status)
+           err = fmt.Errorf("etherscan server: %s", envelope.Message)
+           return
+       }
    }

    // workaround for missing tokenDecimal for some tokentx calls
diff --git a/proxy.go b/proxy.go
new file mode 100644
index 0000000..bf5b255
--- /dev/null
+++ b/proxy.go
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018 LI Zhennan
+ *
+ * Use of this work is governed by a MIT License.
+ * You may find a license copy in project root.
+ */
+
+package etherscan
+
+// ProxyGetTransactionByHash gets the information about a transaction requested by transaction hash.
+func (c *Client) ProxyGetTransactionByHash(txHash string) (obj TransactionObject, err error) {
+   param := M{"txhash": txHash}
+   err = c.call("proxy", "eth_getTransactionByHash", param, &obj)
+   return
+}
diff --git a/response.go b/response.go
index b1338d3..b390942 100644
--- a/response.go
+++ b/response.go
@@ -88,6 +88,23 @@ type ERC20Transfer struct {
    Confirmations     int     `json:"confirmations,string"`
 }

+// TransactionObject holds info from Transaction Object
+type TransactionObject struct {
+   BlockHash        string  `json:"blockHash"`
+   BlockNumber      string  `json:"blockNumber"`
+   From             string  `json:"from"`
+   Gas              string  `json:"gas"`
+   GasPrice         *BigInt `json:"gasPrice"`
+   Input            string  `json:"input"`
+   Nonce            string  `json:"nonce"`
+   To               string  `json:"to"`
+   TransactionIndex string  `json:"transactionIndex"`
+   Value            *BigInt `json:"value"`
+   ECDSARecoveryID  string  `json:"v"`
+   ECDSASignatureR  string  `json:"r"`
+   ECDSASignatureS  string  `json:"s"`
+}
+
 // MinedBlock holds info from query for mined block by address
 type MinedBlock struct {
    BlockNumber int     `json:"blockNumber,string"`

The second difference is that the integers seemed to be hex-encoded and not just string-encoded, so the int json:"key,string" doesn't work here. So here you would need to (for best user experience) also need to ensure that you can return a final Response structure that has it nicely decoded as int, even though these integers are hex-encoded when returned from the Proxy call.

nanmu42 commented 5 years ago

@GlenDC @BenKnigge

After thinking twice, adding proxy to etherscan-api may not be a good idea.

The proxy methods are actually a port on Geth/Parity RPC, where there are public APIs on Infura(https://infura.io) and go package ethclient(https://github.com/ethereum/go-ethereum/tree/master/ethclient), with great availability and type safety.

It makes more sense to call Infura with ethclient, than using proxy APIs on etherscan(well, the name proxy is somewhat self-documented. :laughing: )

Re-inventing the wheel may sound cool, but it would be hard to keep this little package light and tidy when adding functions that ethclient already supports.

Thanks for your kind heart. :+1: