Skip to content

Commit

Permalink
feat: add api for trace tx
Browse files Browse the repository at this point in the history
  • Loading branch information
sunhongtao committed Jan 8, 2024
1 parent db8c3d5 commit 7baa819
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 4 deletions.
2 changes: 1 addition & 1 deletion blockchain/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type API interface {

type ExApi interface {
GasPrice(chainCode int64) (string, error)
TraceTransaction(chainCode int64, address string) (string, error)
TraceTransaction(chainCode int64, hash string) (string, error)
EstimateGas(chainCode int64, from, to, data string) (string, error)
EstimateGasForTron(chainCode int64, from, to, functionSelector, parameter string) (string, error)
GetAccountResourceForTron(chainCode int64, address string) (string, error)
Expand Down
39 changes: 39 additions & 0 deletions blockchain/service/http_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,45 @@ func (h *HttpHandler) GetBlockByNumber(ctx *gin.Context) {
h.Success(ctx, string(b), res, ctx.Request.RequestURI)
}

func (h *HttpHandler) GetTraceTransaction(ctx *gin.Context) {
b, err := io.ReadAll(ctx.Request.Body)
if err != nil {
h.Error(ctx, "", ctx.Request.RequestURI, err.Error())
return
}
blockChainCode := gjson.ParseBytes(b).Get("chain").Int()
hash := gjson.ParseBytes(b).Get("hash").String()
if _, ok := h.exBlockChainClients[blockChainCode]; !ok {
h.Error(ctx, string(b), ctx.Request.RequestURI, fmt.Sprintf("blockchain:%v is not supported", blockChainCode))
return
}
res, err := h.exBlockChainClients[blockChainCode].TraceTransaction(blockChainCode, hash)

if err != nil {
h.Error(ctx, string(b), ctx.Request.RequestURI, err.Error())
return
}

r := make([]*blockchain.InterTx, 0, 10)
if chain.GetChainCode(blockChainCode, "ETH", nil) || chain.GetChainCode(blockChainCode, "BSC", nil) || chain.GetChainCode(blockChainCode, "POLYGON", nil) {
list := gjson.Parse(res).Get("result").Array()
for _, v := range list {
value := v.Get("action.value").String()
if value != "0x0" {
var t blockchain.InterTx
_ = json.Unmarshal([]byte(v.String()), &t)
hexValue, _ := util.HexToInt(t.Action.Value)
t.Action.Value = util.Div(hexValue, 18)
t.Action.Gas, _ = util.HexToInt(t.Action.Gas)
r = append(r, &t)
}
}

}

h.Success(ctx, string(b), r, ctx.Request.RequestURI)
}

func (h *HttpHandler) GetTxByHash(ctx *gin.Context) {
b, err := io.ReadAll(ctx.Request.Body)
if err != nil {
Expand Down
49 changes: 49 additions & 0 deletions blockchain/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,52 @@ type WsRespMessage struct {
Params map[string]string
Resp interface{}
}

/**
{
"action": {
"from": "0x4e68ccd3e89f51c3074ca5072bbac773960dfa36",
"callType": "staticcall",
"gas": "0x26e23",
"input": "0x70a082310000000000000000000000004e68ccd3e89f51c3074ca5072bbac773960dfa36",
"to": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"value": "0x0"
},
"blockHash": "0x6b3f8639a57d744dcbbbe0d84bca25d7ea776282d6f53f329db3cc9408416115",
"blockNumber": 18938364,
"result": {
"gasUsed": "0x9e6",
"output": "0x00000000000000000000000000000000000000000000036e79c74a878ae9c2cd"
},
"subtraces": 0,
"traceAddress": [
1,
1
],
"transactionHash": "0x999cabe1fcca80148290827a8c655734531615cb22d30faa222ec7a67928587b",
"transactionPosition": 201,
"type": "call"
}
*/

type InterTx struct {
Result struct {
Output string `json:"output" gorm:"column:output"`
GasUsed string `json:"gasUsed" gorm:"column:gasUsed"`
} `json:"-" gorm:"column:result"`
BlockHash string `json:"blockHash" gorm:"column:blockHash"`
TransactionPosition int `json:"-" gorm:"column:transactionPosition"`
BlockNumber int `json:"blockNumber" gorm:"column:blockNumber"`
TraceAddress []int `json:"-" gorm:"column:traceAddress"`
Action struct {
Input string `json:"-" gorm:"column:input"`
Gas string `json:"gas" gorm:"column:gas"`
From string `json:"from" gorm:"column:from"`
To string `json:"to" gorm:"column:to"`
Value string `json:"value" gorm:"column:value"`
CallType string `json:"callType" gorm:"column:callType"`
} `json:"action" gorm:"column:action"`
Type string `json:"-" gorm:"column:type"`
Subtraces int `json:"-" gorm:"column:subtraces"`
TransactionHash string `json:"transactionHash" gorm:"column:transactionHash"`
}
45 changes: 45 additions & 0 deletions cmd/blockchain/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,51 @@ curl -X POST \
"message": "ok"
}
//Query trace transaction by txHash for only evm chain
curl -X POST \
http://127.0.0.1:9002/api/chain/origin/tx/trace \
-H 'Content-Type: application/json' \
-H 'Postman-Token: 72b4bc45-c235-4361-b88b-2ccffd42a384' \
-H 'cache-control: no-cache' \
-d '{
"chain":200,
"hash":"0x999cabe1fcca80148290827a8c655734531615cb22d30faa222ec7a67928587b"
}'
response:
{
"code": 0,
"data": [
{
"blockHash": "0x6b3f8639a57d744dcbbbe0d84bca25d7ea776282d6f53f329db3cc9408416115",
"blockNumber": 18938364,
"action": {
"gas": "281806",
"from": "0xae185e9cd79631c5fc19f0fd0454adca8a94976f",
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"value": "0.309648405815618",
"callType": "call"
},
"transactionHash": "0x999cabe1fcca80148290827a8c655734531615cb22d30faa222ec7a67928587b"
},
{
"blockHash": "0x6b3f8639a57d744dcbbbe0d84bca25d7ea776282d6f53f329db3cc9408416115",
"blockNumber": 18938364,
"action": {
"gas": "261730",
"from": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"to": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"value": "0.309648405815618",
"callType": "call"
},
"transactionHash": "0x999cabe1fcca80148290827a8c655734531615cb22d30faa222ec7a67928587b"
}
],
"message": "ok"
}
//Query receipt by txHash
curl -X POST \
http://127.0.0.1:9002/api/chain/origin/receipts/hash \
Expand Down
3 changes: 2 additions & 1 deletion cmd/blockchain/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

func main() {
var configPath string
flag.StringVar(&configPath, "blockchain", "./cmd/blockchain/blockchain_config.json", "The system file of config")
flag.StringVar(&configPath, "blockchain", "./cmd/blockchain/config_ether.json", "The system file of config")
flag.Parse()
if len(configPath) < 1 {
panic("can not find config file")
Expand Down Expand Up @@ -50,6 +50,7 @@ func main() {
origin.POST("/block/hash", srv.GetBlockByHash)
origin.POST("/block/number", srv.GetBlockByNumber)
origin.POST("/tx/hash", srv.GetTxByHash)
origin.POST("/tx/trace", srv.GetTraceTransaction)
origin.POST("/receipts/hash", srv.GetTxReceiptByHash)
origin.POST("/account/balance", srv.GetBalance)
origin.POST("/account/tokenBalance", srv.GetTokenBalance)
Expand Down
5 changes: 3 additions & 2 deletions cmd/blockchain/config_ether.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
"Nodes": [
{
"BlockChain": 200,
"NodeUrl": "https://ethereum.publicnode.com",
"NodeToken": ""
"NodeUrl": "https://docs-demo.quiknode.pro",
"NodeToken": "",
"Trace": true
}
]
}
1 change: 1 addition & 0 deletions cmd/easynode/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ func startBlockchain(configPath string, ctx context.Context) {
origin.POST("/block/hash", srv.GetBlockByHash)
origin.POST("/block/number", srv.GetBlockByNumber)
origin.POST("/tx/hash", srv.GetTxByHash)
origin.POST("/tx/trace", srv.GetTraceTransaction)
origin.POST("/receipts/hash", srv.GetTxReceiptByHash)
origin.POST("/account/balance", srv.GetBalance)
origin.POST("/account/tokenBalance", srv.GetTokenBalance)
Expand Down

0 comments on commit 7baa819

Please sign in to comment.