github.com/Finschia/finschia-sdk@v0.48.1/types/result.go (about) 1 package types 2 3 import ( 4 "encoding/hex" 5 "encoding/json" 6 "math" 7 "strings" 8 9 "github.com/gogo/protobuf/proto" 10 11 ctypes "github.com/Finschia/ostracon/rpc/core/types" 12 abci "github.com/tendermint/tendermint/abci/types" 13 14 "github.com/Finschia/finschia-sdk/codec" 15 codectypes "github.com/Finschia/finschia-sdk/codec/types" 16 ) 17 18 func (gi GasInfo) String() string { 19 bz, _ := codec.MarshalYAML(codec.NewProtoCodec(nil), &gi) 20 return string(bz) 21 } 22 23 func (r Result) String() string { 24 bz, _ := codec.MarshalYAML(codec.NewProtoCodec(nil), &r) 25 return string(bz) 26 } 27 28 func (r Result) GetEvents() Events { 29 events := make(Events, len(r.Events)) 30 for i, e := range r.Events { 31 events[i] = Event(e) 32 } 33 34 return events 35 } 36 37 // ABCIMessageLogs represents a slice of ABCIMessageLog. 38 // 39 //easyjson:json 40 type ABCIMessageLogs []ABCIMessageLog 41 42 func NewABCIMessageLog(i uint32, log string, events Events) ABCIMessageLog { 43 return ABCIMessageLog{ 44 MsgIndex: i, 45 Log: log, 46 Events: StringifyEvents(events.ToABCIEvents()), 47 } 48 } 49 50 // String implements the fmt.Stringer interface for the ABCIMessageLogs type. 51 func (logs ABCIMessageLogs) String() string { 52 if logs != nil { 53 res, err := logs.MarshalJSON() 54 if err != nil { 55 panic(err) 56 } 57 return string(res) 58 } 59 return "" 60 } 61 62 // NewResponseResultTx returns a TxResponse given a ResultTx from ostracon 63 func NewResponseResultTx(res *ctypes.ResultTx, anyTx *codectypes.Any, timestamp string) *TxResponse { 64 if res == nil { 65 return nil 66 } 67 68 parsedLogs, _ := ParseABCILogs(res.TxResult.Log) 69 70 return &TxResponse{ 71 TxHash: res.Hash.String(), 72 Height: res.Height, 73 Codespace: res.TxResult.Codespace, 74 Code: res.TxResult.Code, 75 Data: strings.ToUpper(hex.EncodeToString(res.TxResult.Data)), 76 RawLog: res.TxResult.Log, 77 Logs: parsedLogs, 78 Info: res.TxResult.Info, 79 GasWanted: res.TxResult.GasWanted, 80 GasUsed: res.TxResult.GasUsed, 81 Tx: anyTx, 82 Timestamp: timestamp, 83 Events: res.TxResult.Events, 84 } 85 } 86 87 // NewResponseFormatBroadcastTxCommit returns a TxResponse given a 88 // ResultBroadcastTxCommit from ostracon. 89 func NewResponseFormatBroadcastTxCommit(res *ctypes.ResultBroadcastTxCommit) *TxResponse { 90 if res == nil { 91 return nil 92 } 93 94 if !res.CheckTx.IsOK() { 95 return newTxResponseCheckTx(res) 96 } 97 98 return newTxResponseDeliverTx(res) 99 } 100 101 func newTxResponseCheckTx(res *ctypes.ResultBroadcastTxCommit) *TxResponse { 102 if res == nil { 103 return nil 104 } 105 106 var txHash string 107 if res.Hash != nil { 108 txHash = res.Hash.String() 109 } 110 111 parsedLogs, _ := ParseABCILogs(res.CheckTx.Log) 112 113 return &TxResponse{ 114 Height: res.Height, 115 TxHash: txHash, 116 Codespace: res.CheckTx.Codespace, 117 Code: res.CheckTx.Code, 118 Data: strings.ToUpper(hex.EncodeToString(res.CheckTx.Data)), 119 RawLog: res.CheckTx.Log, 120 Logs: parsedLogs, 121 Info: res.CheckTx.Info, 122 GasWanted: res.CheckTx.GasWanted, 123 GasUsed: res.CheckTx.GasUsed, 124 Events: res.CheckTx.Events, 125 } 126 } 127 128 func newTxResponseDeliverTx(res *ctypes.ResultBroadcastTxCommit) *TxResponse { 129 if res == nil { 130 return nil 131 } 132 133 var txHash string 134 if res.Hash != nil { 135 txHash = res.Hash.String() 136 } 137 138 parsedLogs, _ := ParseABCILogs(res.DeliverTx.Log) 139 140 return &TxResponse{ 141 Height: res.Height, 142 TxHash: txHash, 143 Codespace: res.DeliverTx.Codespace, 144 Code: res.DeliverTx.Code, 145 Data: strings.ToUpper(hex.EncodeToString(res.DeliverTx.Data)), 146 RawLog: res.DeliverTx.Log, 147 Logs: parsedLogs, 148 Info: res.DeliverTx.Info, 149 GasWanted: res.DeliverTx.GasWanted, 150 GasUsed: res.DeliverTx.GasUsed, 151 Events: res.DeliverTx.Events, 152 } 153 } 154 155 // NewResponseFormatBroadcastTx returns a TxResponse given a ResultBroadcastTx from ostracon 156 func NewResponseFormatBroadcastTx(res *ctypes.ResultBroadcastTx) *TxResponse { 157 if res == nil { 158 return nil 159 } 160 161 parsedLogs, _ := ParseABCILogs(res.Log) 162 163 return &TxResponse{ 164 Code: res.Code, 165 Codespace: res.Codespace, 166 Data: res.Data.String(), 167 RawLog: res.Log, 168 Logs: parsedLogs, 169 TxHash: res.Hash.String(), 170 } 171 } 172 173 func (r TxResponse) String() string { 174 bz, _ := codec.MarshalYAML(codec.NewProtoCodec(nil), &r) 175 return string(bz) 176 } 177 178 // Empty returns true if the response is empty 179 func (r TxResponse) Empty() bool { 180 return r.TxHash == "" && r.Logs == nil 181 } 182 183 func NewSearchTxsResult(totalCount, count, page, limit uint64, txs []*TxResponse) *SearchTxsResult { 184 return &SearchTxsResult{ 185 TotalCount: totalCount, 186 Count: count, 187 PageNumber: page, 188 PageTotal: uint64(math.Ceil(float64(totalCount) / float64(limit))), 189 Limit: limit, 190 Txs: txs, 191 } 192 } 193 194 // ParseABCILogs attempts to parse a stringified ABCI tx log into a slice of 195 // ABCIMessageLog types. It returns an error upon JSON decoding failure. 196 func ParseABCILogs(logs string) (res ABCIMessageLogs, err error) { 197 err = json.Unmarshal([]byte(logs), &res) 198 return res, err 199 } 200 201 var _, _ codectypes.UnpackInterfacesMessage = SearchTxsResult{}, TxResponse{} 202 203 // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces 204 // 205 // types.UnpackInterfaces needs to be called for each nested Tx because 206 // there are generally interfaces to unpack in Tx's 207 func (s SearchTxsResult) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 208 for _, tx := range s.Txs { 209 err := codectypes.UnpackInterfaces(tx, unpacker) 210 if err != nil { 211 return err 212 } 213 } 214 return nil 215 } 216 217 // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces 218 func (r TxResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 219 if r.Tx != nil { 220 var tx Tx 221 return unpacker.UnpackAny(r.Tx, &tx) 222 } 223 return nil 224 } 225 226 // GetTx unpacks the Tx from within a TxResponse and returns it 227 func (r TxResponse) GetTx() Tx { 228 if tx, ok := r.Tx.GetCachedValue().(Tx); ok { 229 return tx 230 } 231 return nil 232 } 233 234 // WrapServiceResult wraps a result from a protobuf RPC service method call in 235 // a Result object or error. This method takes care of marshaling the res param to 236 // protobuf and attaching any events on the ctx.EventManager() to the Result. 237 func WrapServiceResult(ctx Context, res proto.Message, err error) (*Result, error) { 238 if err != nil { 239 return nil, err 240 } 241 242 var data []byte 243 if res != nil { 244 data, err = proto.Marshal(res) 245 if err != nil { 246 return nil, err 247 } 248 } 249 250 var events []abci.Event 251 if evtMgr := ctx.EventManager(); evtMgr != nil { 252 events = evtMgr.ABCIEvents() 253 } 254 255 return &Result{ 256 Data: data, 257 Events: events, 258 }, nil 259 }