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  }