From 2671596dab11ad204fff42fc0d55d2f7436054b8 Mon Sep 17 00:00:00 2001 From: thanhpp Date: Thu, 16 May 2024 10:17:24 +0700 Subject: [PATCH] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20eth/trace:=20h?= =?UTF-8?q?andle=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: thanhpp --- pkg/eth/trace.go | 157 +++++++++++++++++++++++++---------------------- 1 file changed, 84 insertions(+), 73 deletions(-) diff --git a/pkg/eth/trace.go b/pkg/eth/trace.go index 80ba594..9bed54d 100644 --- a/pkg/eth/trace.go +++ b/pkg/eth/trace.go @@ -4,6 +4,7 @@ import ( "bytes" "cmp" "encoding/json" + "fmt" "io" "math/big" "net/http" @@ -41,67 +42,16 @@ func (c *TraceClient) DebugTraceTransaction(txHash string) (CallFrame, error) { }, } - b, err := json.Marshal(payload) - if err != nil { - return CallFrame{}, err - } - - req, err := http.NewRequest(http.MethodPost, c.rpcURL, bytes.NewBuffer(b)) - if err != nil { - return CallFrame{}, err - } - req.Header.Add("Content-Type", "application/json") - - res, err := c.httpClient.Do(req) - if err != nil { - return CallFrame{}, err - } - defer res.Body.Close() - - body, err := io.ReadAll(res.Body) - if err != nil { - return CallFrame{}, err + var resp CommomTraceResponse[CallFrame] + if err := c.post(payload, &resp); err != nil { + return CallFrame{}, fmt.Errorf("post error: %w", err) } - - var rpcResponse CommomTraceResponse[CallFrame] - if err := json.Unmarshal(body, &rpcResponse); err != nil { - return CallFrame{}, err - } - - return rpcResponse.Result, err -} - -type CommomTraceResponse[T any] struct { - Jsonrpc string `json:"jsonrpc"` - ID int `json:"id"` - Result T `json:"result"` -} - -type CallLog struct { - Address common.Address `json:"address"` - Topics []common.Hash `json:"topics"` - Data string `json:"data"` -} - -func (l CallLog) ToEthereumLog() types.Log { - return types.Log{ - Address: l.Address, - Topics: l.Topics, - Data: common.Hex2Bytes(l.Data), + if resp.Error.Code != 0 { + return CallFrame{}, fmt.Errorf("error response: code: %d, message: %s", + resp.Error.Code, resp.Error.Message) } -} -type CallFrame struct { - From string `json:"from"` - Gas string `json:"gas"` - GasUsed string `json:"gasUsed"` - To string `json:"to"` - Input string `json:"input"` - Output string `json:"output"` - Calls []CallFrame `json:"calls"` - Value string `json:"value"` - Type string `json:"type"` - Logs []CallLog `json:"logs"` + return resp.Result, nil } func (c *TraceClient) DebugTraceCall( @@ -148,32 +98,93 @@ func (c *TraceClient) DebugTraceCall( }, } - b, err := json.Marshal(payload) - if err != nil { - return CallFrame{}, err + var resp CommomTraceResponse[CallFrame] + if err := c.post(payload, &resp); err != nil { + return CallFrame{}, fmt.Errorf("post error: %w", err) + } + + if resp.Error.Code != 0 { + return CallFrame{}, fmt.Errorf("error response: code: %d, message: %s", + resp.Error.Code, resp.Error.Message) } - req, err := http.NewRequest(http.MethodPost, c.rpcURL, bytes.NewBuffer(b)) + return resp.Result, nil +} + +func (c *TraceClient) post(payload any, expect any) error { + var body *bytes.Buffer + if payload != nil { + b, err := json.Marshal(payload) + if err != nil { + return fmt.Errorf("marshal error: %w", err) + } + body = bytes.NewBuffer(b) + } + + req, err := http.NewRequest(http.MethodPost, c.rpcURL, body) if err != nil { - return CallFrame{}, err + return err } req.Header.Add("Content-Type", "application/json") - res, err := c.httpClient.Do(req) + resp, err := c.httpClient.Do(req) if err != nil { - return CallFrame{}, err + return err } - defer res.Body.Close() - - text, err := io.ReadAll(res.Body) + defer resp.Body.Close() + text, err := io.ReadAll(resp.Body) if err != nil { - return CallFrame{}, err + return err } - var rpcResponse CommomTraceResponse[CallFrame] - if err := json.Unmarshal(text, &rpcResponse); err != nil { - return CallFrame{}, err + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("not status OK, status: %d", resp.StatusCode) + } + + if expect != nil { + if err := json.Unmarshal(text, expect); err != nil { + return fmt.Errorf("unmarshal error: %w, data: [%s]", err, text) + } + } + + return nil +} + +type CommomTraceResponse[T any] struct { + JSONRPC string `json:"jsonrpc"` + ID int `json:"id"` + Result T `json:"result"` + Error ErrorResponse `json:"error"` +} + +type CallLog struct { + Address common.Address `json:"address"` + Topics []common.Hash `json:"topics"` + Data string `json:"data"` +} + +func (l CallLog) ToEthereumLog() types.Log { + return types.Log{ + Address: l.Address, + Topics: l.Topics, + Data: common.Hex2Bytes(l.Data), } +} + +type CallFrame struct { + From string `json:"from"` + Gas string `json:"gas"` + GasUsed string `json:"gasUsed"` + To string `json:"to"` + Input string `json:"input"` + Output string `json:"output"` + Calls []CallFrame `json:"calls"` + Value string `json:"value"` + Type string `json:"type"` + Logs []CallLog `json:"logs"` +} - return rpcResponse.Result, err +type ErrorResponse struct { + Code int64 `json:"code"` + Message string `json:"message"` }