github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/transaction_receipt.go (about) 1 package hedera 2 3 /*- 4 * 5 * Hedera Go SDK 6 * 7 * Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 */ 22 23 import ( 24 "encoding/hex" 25 "encoding/json" 26 "fmt" 27 "reflect" 28 "time" 29 30 "github.com/hashgraph/hedera-protobufs-go/services" 31 protobuf "google.golang.org/protobuf/proto" 32 ) 33 34 // The consensus result for a transaction, which might not be currently known, or may succeed or fail. 35 type TransactionReceipt struct { 36 Status Status 37 ExchangeRate *ExchangeRate 38 TopicID *TopicID 39 FileID *FileID 40 ContractID *ContractID 41 AccountID *AccountID 42 TokenID *TokenID 43 TopicSequenceNumber uint64 44 TopicRunningHash []byte 45 TopicRunningHashVersion uint64 46 TotalSupply uint64 47 ScheduleID *ScheduleID 48 ScheduledTransactionID *TransactionID 49 SerialNumbers []int64 50 NodeID uint64 51 Duplicates []TransactionReceipt 52 Children []TransactionReceipt 53 TransactionID *TransactionID 54 } 55 56 func (receipt *TransactionReceipt) _ToMap() map[string]interface{} { 57 m := map[string]interface{}{ 58 "status": receipt.Status.String(), 59 "topicSequenceNumber": receipt.TopicSequenceNumber, 60 "topicRunningHash": hex.EncodeToString(receipt.TopicRunningHash), 61 "topicRunningHashVersion": receipt.TopicRunningHashVersion, 62 "totalSupply": receipt.TotalSupply, 63 "serialNumbers": receipt.SerialNumbers, 64 "nodeId": receipt.NodeID, 65 } 66 67 // The real ExchangeRate struct has cents and ExpirationTime fields as private, so they can't be marshalled directly 68 type ExchangeRateJSON struct { 69 Hbars int32 `json:"hbars"` 70 Cents int32 `json:"cents"` 71 ExpirationTime string `json:"expirationTime"` 72 } 73 74 if receipt.ExchangeRate != nil { 75 const layout = "2006-01-02T15:04:05.000Z" 76 expiration := time.Unix(receipt.ExchangeRate.expirationTime.Seconds, 0) 77 expirationStr := expiration.UTC().Format(layout) 78 79 m["exchangeRate"] = ExchangeRateJSON{ 80 Hbars: receipt.ExchangeRate.Hbars, 81 Cents: receipt.ExchangeRate.cents, 82 ExpirationTime: expirationStr, 83 } 84 } 85 86 // Handling fields with possible nil values 87 fields := map[string]interface{}{ 88 "topicId": receipt.TopicID, 89 "fileId": receipt.FileID, 90 "contractId": receipt.ContractID, 91 "accountId": receipt.AccountID, 92 "tokenId": receipt.TokenID, 93 "scheduleId": receipt.ScheduleID, 94 "scheduledTransactionId": receipt.ScheduledTransactionID, 95 } 96 for key, field := range fields { 97 m[key] = nil 98 if !reflect.ValueOf(field).IsNil() { 99 m[key] = fmt.Sprintf("%v", field) 100 } 101 } 102 103 m["children"] = receipt.Children 104 m["duplicates"] = receipt.Duplicates 105 return m 106 } 107 108 // MarshalJSON returns the JSON representation of the TransactionReceipt. 109 // This should yield the same result in all SDK's. 110 func (receipt TransactionReceipt) MarshalJSON() ([]byte, error) { 111 return json.Marshal(receipt._ToMap()) 112 } 113 114 func _TransactionReceiptFromProtobuf(protoResponse *services.TransactionGetReceiptResponse, transactionID *TransactionID) TransactionReceipt { 115 if protoResponse == nil { 116 return TransactionReceipt{} 117 } 118 protoReceipt := protoResponse.GetReceipt() 119 if protoReceipt == nil { 120 return TransactionReceipt{} 121 } 122 var accountID *AccountID 123 if protoReceipt.AccountID != nil { 124 accountID = _AccountIDFromProtobuf(protoReceipt.AccountID) 125 } 126 127 var contractID *ContractID 128 if protoReceipt.ContractID != nil { 129 contractID = _ContractIDFromProtobuf(protoReceipt.ContractID) 130 } 131 132 var fileID *FileID 133 if protoReceipt.FileID != nil { 134 fileID = _FileIDFromProtobuf(protoReceipt.FileID) 135 } 136 137 var topicID *TopicID 138 if protoReceipt.TopicID != nil { 139 topicID = _TopicIDFromProtobuf(protoReceipt.TopicID) 140 } 141 142 var rate *ExchangeRate 143 if protoReceipt.ExchangeRate != nil { 144 exchangeRateValue := _ExchangeRateFromProtobuf(protoReceipt.ExchangeRate.GetCurrentRate()) 145 rate = &exchangeRateValue 146 } 147 148 var topicSequenceHash []byte 149 if protoReceipt.TopicRunningHash != nil { 150 topicHash := protoReceipt.TopicRunningHash 151 topicSequenceHash = topicHash 152 } 153 154 var tokenID *TokenID 155 if protoReceipt.TokenID != nil { 156 tokenID = _TokenIDFromProtobuf(protoReceipt.TokenID) 157 } 158 159 var scheduleID *ScheduleID 160 if protoReceipt.ScheduleID != nil { 161 scheduleID = _ScheduleIDFromProtobuf(protoReceipt.ScheduleID) 162 } 163 164 var scheduledTransactionID *TransactionID 165 if protoReceipt.ScheduledTransactionID != nil { 166 scheduledTransactionIDValue := _TransactionIDFromProtobuf(protoReceipt.ScheduledTransactionID) 167 scheduledTransactionID = &scheduledTransactionIDValue 168 } 169 170 childReceipts := make([]TransactionReceipt, 0) 171 if len(protoResponse.ChildTransactionReceipts) > 0 { 172 for _, r := range protoResponse.ChildTransactionReceipts { 173 childReceipts = append(childReceipts, _TransactionReceiptFromProtobuf(&services.TransactionGetReceiptResponse{Receipt: r}, transactionID)) 174 } 175 } 176 177 duplicateReceipts := make([]TransactionReceipt, 0) 178 if len(protoResponse.DuplicateTransactionReceipts) > 0 { 179 for _, r := range protoResponse.DuplicateTransactionReceipts { 180 duplicateReceipts = append(duplicateReceipts, _TransactionReceiptFromProtobuf(&services.TransactionGetReceiptResponse{Receipt: r}, transactionID)) 181 } 182 } 183 184 return TransactionReceipt{ 185 Status: Status(protoReceipt.Status), 186 ExchangeRate: rate, 187 TopicID: topicID, 188 FileID: fileID, 189 ContractID: contractID, 190 AccountID: accountID, 191 TopicSequenceNumber: protoReceipt.TopicSequenceNumber, 192 TopicRunningHash: topicSequenceHash, 193 TopicRunningHashVersion: protoReceipt.TopicRunningHashVersion, 194 TokenID: tokenID, 195 TotalSupply: protoReceipt.NewTotalSupply, 196 ScheduleID: scheduleID, 197 ScheduledTransactionID: scheduledTransactionID, 198 SerialNumbers: protoReceipt.SerialNumbers, 199 NodeID: protoReceipt.NodeId, 200 Children: childReceipts, 201 Duplicates: duplicateReceipts, 202 TransactionID: transactionID, 203 } 204 } 205 206 func (receipt TransactionReceipt) _ToProtobuf() *services.TransactionGetReceiptResponse { 207 receiptFinal := services.TransactionReceipt{ 208 Status: services.ResponseCodeEnum(receipt.Status), 209 TopicSequenceNumber: receipt.TopicSequenceNumber, 210 TopicRunningHash: receipt.TopicRunningHash, 211 TopicRunningHashVersion: receipt.TopicRunningHashVersion, 212 NewTotalSupply: receipt.TotalSupply, 213 SerialNumbers: receipt.SerialNumbers, 214 NodeId: receipt.NodeID, 215 } 216 217 if receipt.ExchangeRate != nil { 218 receiptFinal.ExchangeRate = &services.ExchangeRateSet{ 219 CurrentRate: receipt.ExchangeRate._ToProtobuf(), 220 NextRate: receipt.ExchangeRate._ToProtobuf(), 221 } 222 } 223 224 if receipt.TopicID != nil { 225 receiptFinal.TopicID = receipt.TopicID._ToProtobuf() 226 } 227 228 if receipt.FileID != nil { 229 receiptFinal.FileID = receipt.FileID._ToProtobuf() 230 } 231 232 if receipt.ContractID != nil { 233 receiptFinal.ContractID = receipt.ContractID._ToProtobuf() 234 } 235 236 if receipt.AccountID != nil { 237 receiptFinal.AccountID = receipt.AccountID._ToProtobuf() 238 } 239 240 if receipt.TokenID != nil { 241 receiptFinal.TokenID = receipt.TokenID._ToProtobuf() 242 } 243 244 if receipt.ScheduleID != nil { 245 receiptFinal.ScheduleID = receipt.ScheduleID._ToProtobuf() 246 } 247 248 if receipt.ScheduledTransactionID != nil { 249 receiptFinal.ScheduledTransactionID = receipt.ScheduledTransactionID._ToProtobuf() 250 } 251 252 childReceipts := make([]*services.TransactionReceipt, 0) 253 if len(receipt.Children) > 0 { 254 for _, r := range receipt.Children { 255 childReceipts = append(childReceipts, r._ToProtobuf().GetReceipt()) 256 } 257 } 258 259 duplicateReceipts := make([]*services.TransactionReceipt, 0) 260 if len(receipt.Duplicates) > 0 { 261 for _, r := range receipt.Duplicates { 262 duplicateReceipts = append(duplicateReceipts, r._ToProtobuf().GetReceipt()) 263 } 264 } 265 266 return &services.TransactionGetReceiptResponse{ 267 Receipt: &receiptFinal, 268 ChildTransactionReceipts: childReceipts, 269 DuplicateTransactionReceipts: duplicateReceipts, 270 } 271 } 272 273 // ValidateStatus validates the status of the receipt 274 func (receipt TransactionReceipt) ValidateStatus(shouldValidate bool) error { 275 if shouldValidate && receipt.Status != StatusSuccess && receipt.Status != StatusFeeScheduleFilePartUploaded { 276 if receipt.TransactionID != nil { 277 return _NewErrHederaReceiptStatus(*receipt.TransactionID, receipt.Status) 278 } 279 return _NewErrHederaReceiptStatus(TransactionID{}, receipt.Status) 280 } 281 282 return nil 283 } 284 285 // ToBytes returns the byte representation of the receipt 286 func (receipt TransactionReceipt) ToBytes() []byte { 287 data, err := protobuf.Marshal(receipt._ToProtobuf()) 288 if err != nil { 289 return make([]byte, 0) 290 } 291 292 return data 293 } 294 295 // TransactionReceiptFromBytes returns the receipt from the byte representation 296 func TransactionReceiptFromBytes(data []byte) (TransactionReceipt, error) { 297 if data == nil { 298 return TransactionReceipt{}, errByteArrayNull 299 } 300 pb := services.TransactionGetReceiptResponse{} 301 err := protobuf.Unmarshal(data, &pb) 302 if err != nil { 303 return TransactionReceipt{}, err 304 } 305 306 return _TransactionReceiptFromProtobuf(&pb, nil), nil 307 }