github.com/okex/exchain@v1.8.0/libs/tendermint/rpc/core/tx.go (about) 1 package core 2 3 import ( 4 "fmt" 5 "sort" 6 7 "github.com/pkg/errors" 8 9 tmmath "github.com/okex/exchain/libs/tendermint/libs/math" 10 tmquery "github.com/okex/exchain/libs/tendermint/libs/pubsub/query" 11 ctypes "github.com/okex/exchain/libs/tendermint/rpc/core/types" 12 rpctypes "github.com/okex/exchain/libs/tendermint/rpc/jsonrpc/types" 13 "github.com/okex/exchain/libs/tendermint/state/txindex/null" 14 "github.com/okex/exchain/libs/tendermint/types" 15 ) 16 17 // Tx allows you to query the transaction results. `nil` could mean the 18 // transaction is in the mempool, invalidated, or was not sent in the first 19 // place. 20 // More: https://docs.tendermint.com/master/rpc/#/Info/tx 21 func Tx(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) { 22 // if index is disabled, return error 23 if _, ok := env.TxIndexer.(*null.TxIndex); ok { 24 return nil, fmt.Errorf("transaction indexing is disabled") 25 } 26 27 r, err := env.TxIndexer.Get(hash) 28 if err != nil { 29 return nil, err 30 } 31 32 if r == nil { 33 return nil, fmt.Errorf("tx (%X) not found", hash) 34 } 35 36 height := r.Height 37 index := r.Index 38 39 var proof types.TxProof 40 if prove { 41 block := env.BlockStore.LoadBlock(height) 42 proof = block.Data.Txs.Proof(int(index), block.Height) // XXX: overflow on 32-bit machines 43 } 44 45 return &ctypes.ResultTx{ 46 Hash: hash, 47 Height: height, 48 Index: index, 49 TxResult: r.Result, 50 Tx: r.Tx, 51 Proof: proof, 52 }, nil 53 } 54 55 // TxSearch allows you to query for multiple transactions results. It returns a 56 // list of transactions (maximum ?per_page entries) and the total count. 57 // More: https://docs.tendermint.com/master/rpc/#/Info/tx_search 58 func TxSearch(ctx *rpctypes.Context, query string, prove bool, page, perPage int, orderBy string) ( 59 *ctypes.ResultTxSearch, error) { 60 // if index is disabled, return error 61 if _, ok := env.TxIndexer.(*null.TxIndex); ok { 62 return nil, errors.New("transaction indexing is disabled") 63 } 64 65 q, err := tmquery.New(query) 66 if err != nil { 67 return nil, err 68 } 69 70 results, err := env.TxIndexer.Search(ctx.Context(), q) 71 if err != nil { 72 return nil, err 73 } 74 75 // sort results (must be done before pagination) 76 switch orderBy { 77 case "desc": 78 sort.Slice(results, func(i, j int) bool { 79 if results[i].Height == results[j].Height { 80 return results[i].Index > results[j].Index 81 } 82 return results[i].Height > results[j].Height 83 }) 84 case "asc", "": 85 sort.Slice(results, func(i, j int) bool { 86 if results[i].Height == results[j].Height { 87 return results[i].Index < results[j].Index 88 } 89 return results[i].Height < results[j].Height 90 }) 91 default: 92 return nil, errors.New("expected order_by to be either `asc` or `desc` or empty") 93 } 94 95 // paginate results 96 totalCount := len(results) 97 perPage = validatePerPage(perPage) 98 page, err = validatePage(page, perPage, totalCount) 99 if err != nil { 100 return nil, err 101 } 102 skipCount := validateSkipCount(page, perPage) 103 pageSize := tmmath.MinInt(perPage, totalCount-skipCount) 104 105 apiResults := make([]*ctypes.ResultTx, 0, pageSize) 106 for i := skipCount; i < skipCount+pageSize; i++ { 107 r := results[i] 108 109 var proof types.TxProof 110 if prove { 111 block := env.BlockStore.LoadBlock(r.Height) 112 proof = block.Data.Txs.Proof(int(r.Index), block.Height) // XXX: overflow on 32-bit machines 113 } 114 115 apiResults = append(apiResults, &ctypes.ResultTx{ 116 Hash: r.Tx.Hash(r.Height), 117 Height: r.Height, 118 Index: r.Index, 119 TxResult: r.Result, 120 Tx: r.Tx, 121 Proof: proof, 122 }) 123 } 124 125 return &ctypes.ResultTxSearch{Txs: apiResults, TotalCount: totalCount}, nil 126 }