From 69df9b7f748a9449163c98012b9e84b3c3f176ed Mon Sep 17 00:00:00 2001 From: Casian Lacatusu Date: Thu, 7 Nov 2019 13:52:58 +0200 Subject: [PATCH 1/3] add msgError and msgErrorString for backwards compatibility with the explorer --- api/handlers_tx.go | 16 ++++++++++++++-- api/types/tx.go | 2 ++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/api/handlers_tx.go b/api/handlers_tx.go index c1f39ec..930d4fb 100644 --- a/api/handlers_tx.go +++ b/api/handlers_tx.go @@ -44,7 +44,7 @@ func (a *API) TxDetailsHandler(c *gin.Context) { return } - OK(c, types.Tx{ + tx := types.Tx{ TxHash: &txHash, IncludedInBlock: &includedInBlock, TxIndex: &txIndex, @@ -62,7 +62,19 @@ func (a *API) TxDetailsHandler(c *gin.Context) { TxLogsBloom: &txLogsBloom, BlockCreationTime: &blockCreationTime, LogEntriesTriggered: &logEntriesTriggered, - }) + } + + var msgError bool + var msgErrorString string + if tx.MsgStatus != nil && *tx.MsgStatus == "0x0" { + msgError = true + msgErrorString = "Error" + } + + tx.MsgError = &msgError + tx.MsgErrorString = &msgErrorString + + OK(c, tx) } func (a *API) TxLogEntriesHandler(c *gin.Context) { diff --git a/api/types/tx.go b/api/types/tx.go index 1e9cb4f..b09ec60 100644 --- a/api/types/tx.go +++ b/api/types/tx.go @@ -16,6 +16,8 @@ type Tx struct { CumulativeGasUsed *string `json:"cumulativeGasUsed,omitempty"` MsgPayload *storable.ByteArray `json:"msgPayload,omitempty"` MsgStatus *string `json:"msgStatus,omitempty"` + MsgError *bool `json:"msgError,omitempty"` + MsgErrorString *string `json:"msgErrorString,omitempty"` Creates *storable.ByteArray `json:"creates,omitempty"` TxLogsBloom *storable.ByteArray `json:"txLogsBloom,omitempty"` BlockCreationTime *storable.DatetimeToJSONUnix `json:"blockCreationTime,omitempty"` From 731ba849e9c6663b51a781ea72e6a1739cf95529 Mon Sep 17 00:00:00 2001 From: Casian Lacatusu Date: Fri, 8 Nov 2019 13:42:58 +0200 Subject: [PATCH 2/3] implement search endpoint for explorer api --- api/handlers_search.go | 63 ++++++++++++++++++++++++++++++++++++++++++ api/routes.go | 1 + 2 files changed, 64 insertions(+) create mode 100644 api/handlers_search.go diff --git a/api/handlers_search.go b/api/handlers_search.go new file mode 100644 index 0000000..371e4a6 --- /dev/null +++ b/api/handlers_search.go @@ -0,0 +1,63 @@ +package api + +import ( + "database/sql" + "fmt" + + "github.com/Alethio/memento/utils" + "github.com/gin-gonic/gin" +) + +func (a *API) SearchHandler(c *gin.Context) { + query := utils.CleanUpHex(c.Param("query")) + + if len(query) != 64 { + BadRequest(c, fmt.Errorf("invalid request: invalid query string")) + return + } + + var count int + err := a.core.DB().QueryRow(`select count(*) from txs where tx_hash = $1`, query).Scan(&count) + if err != nil { + Error(c, err) + return + } + if count > 0 { + OK(c, map[string]interface{}{ + "entity": "tx", + "data": nil, + }) + return + } + + var number int64 + err = a.core.DB().QueryRow(`select number from blocks where block_hash = $1`, query).Scan(&number) + if err != nil && err != sql.ErrNoRows { + Error(c, err) + return + } + if err != sql.ErrNoRows { + OK(c, map[string]interface{}{ + "entity": "block", + "data": map[string]interface{}{ + "number": number, + }, + }) + return + } + + err = a.core.DB().QueryRow(`select count(*) from uncles where block_hash = $1`, query).Scan(&count) + if err != nil { + Error(c, err) + return + } + if count > 0 { + OK(c, map[string]interface{}{ + "entity": "uncle", + "data": nil, + }) + return + } + + OK(c, map[string]interface{}{}) +} diff --git a/api/routes.go b/api/routes.go index 3917d5e..53d8b8a 100644 --- a/api/routes.go +++ b/api/routes.go @@ -8,4 +8,5 @@ func (a *API) setRoutes() { explorer.GET("/tx/:txHash", a.TxDetailsHandler) explorer.GET("/tx/:txHash/log-entries", a.TxLogEntriesHandler) explorer.GET("/account/:address/txs", a.AccountTxsHandler) + explorer.GET("/search/:query", a.SearchHandler) } From 0d5742b558ed300d76f877b48e41b465b77fe137 Mon Sep 17 00:00:00 2001 From: Casian Lacatusu Date: Fri, 8 Nov 2019 15:27:23 +0200 Subject: [PATCH 3/3] add proxy endpoints for account balance and account code --- api/api.go | 1 + api/handlers_account.go | 58 +++++++++++++++++++++++++++++++++++++++++ api/routes.go | 5 +++- commands/run.go | 1 + 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 api/handlers_account.go diff --git a/api/api.go b/api/api.go index a29fe56..ddb7103 100644 --- a/api/api.go +++ b/api/api.go @@ -13,6 +13,7 @@ type Config struct { Port string DevCorsEnabled bool DevCorsHost string + EthClientURL string } type API struct { diff --git a/api/handlers_account.go b/api/handlers_account.go new file mode 100644 index 0000000..4f30f85 --- /dev/null +++ b/api/handlers_account.go @@ -0,0 +1,58 @@ +package api + +import ( + "encoding/hex" + "fmt" + + "github.com/Alethio/memento/utils" + "github.com/alethio/web3-go/ethrpc" + "github.com/gin-gonic/gin" +) + +func (a *API) AccountCodeHandler(c *gin.Context) { + address := utils.CleanUpHex(c.Param("address")) + if len(address) != 40 { + BadRequest(c, fmt.Errorf("bad request: address is malformed")) + return + } + + eth, err := ethrpc.NewWithDefaults(a.config.EthClientURL) + if err != nil { + Error(c, err) + return + } + + code, err := eth.GetCode(fmt.Sprintf("0x%s", address)) + if err != nil { + Error(c, err) + return + } + + OK(c, map[string]interface{}{ + "code": hex.EncodeToString(code), + }) +} + +func (a *API) AccountBalanceHandler(c *gin.Context) { + address := utils.CleanUpHex(c.Param("address")) + if len(address) != 40 { + BadRequest(c, fmt.Errorf("bad request: address is malformed")) + return + } + + eth, err := ethrpc.NewWithDefaults(a.config.EthClientURL) + if err != nil { + Error(c, err) + return + } + + balance, err := eth.GetBalanceAtBlock(fmt.Sprintf("0x%s", address), fmt.Sprintf("0x%x", a.core.Metrics().GetLatestBLock())) + if err != nil { + Error(c, err) + return + } + + OK(c, map[string]interface{}{ + "balance": balance.String(), + }) +} diff --git a/api/routes.go b/api/routes.go index 53d8b8a..d85fa2b 100644 --- a/api/routes.go +++ b/api/routes.go @@ -7,6 +7,9 @@ func (a *API) setRoutes() { explorer.GET("/uncle/:hash", a.UncleDetailsHandler) explorer.GET("/tx/:txHash", a.TxDetailsHandler) explorer.GET("/tx/:txHash/log-entries", a.TxLogEntriesHandler) - explorer.GET("/account/:address/txs", a.AccountTxsHandler) explorer.GET("/search/:query", a.SearchHandler) + + explorer.GET("/account/:address/txs", a.AccountTxsHandler) + explorer.GET("/account/:address/code", a.AccountCodeHandler) + explorer.GET("/account/:address/balance", a.AccountBalanceHandler) } diff --git a/commands/run.go b/commands/run.go index c487fba..01162d8 100644 --- a/commands/run.go +++ b/commands/run.go @@ -67,6 +67,7 @@ var runCmd = &cobra.Command{ Port: viper.GetString("api.port"), DevCorsEnabled: viper.GetBool("api.dev-cors"), DevCorsHost: viper.GetString("api.dev-cors-host"), + EthClientURL: viper.GetString("eth.client.http"), }) go a.Run()