Interestingly, Hyperledger Fabric has its own error-handling package, github.com/pkg/errors, which allows you to handle errors in a much better way than the built-in error handling provided by Go. For example:
import (
"fmt"
"github.com/pkg/errors"
)
//wrapping error with stack
func wrapWithStack() error {
err := displayError ()
return errors.Wrap(err, "wrapping an application error with stack trace")
}
func displayError() error {
return errors.New("example error message")
}
func main() {
err := displayError()
fmt.Printf("print error without stack trace: %s\n\n", err)
fmt.Printf("print error with stack trace: %+v\n\n", err)
err = wrapWithStack()
fmt.Printf("%+v\n\n", err)
}
The aforementioned package provides several helpful functions. For instance, error.wrap is used to generate a call stack trace for a given error (the standard error handling does not come with stack traces), which is very helpful for debugging, while error.New generates a new error with the supplied message and records the stack trace at the point it was called. The shim package also provides an error-handling method, shim.error(), which returns an error message with a serialized response to the client.
As an example, we can define the initiateShipment function as the following, with the ability to warn the client if an error occurs using shim.error as follows:
func (f *FoodContract) initiateShipment(stub shim.ChaincodeStubInterface, args []string) pb.Response {
orderId := args[0]
foodBytes, err := stub.GetState(orderId)
fd := food{}
err = json.Unmarshal(foodBytes, &fd)
if err != nil {
return shim.Error(err.Error())
}
if fd.Status == "wholesaler distribute" {
fd.LogisticsId = "LogisticsId_1"
currentts := time.Now()
fd.ShippingProcessDate = currentts.Format("2006-01-02 15:04:05")
fd.Status = "initiated shipment"
} else {
fmt.Printf("Wholesaler not initiated yet")
}
foodBytes0, _ := json.Marshal(fd)
err = stub.PutState(orderId, foodBytes0)
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
At this level, we have successfully written the main parts of our first Chaincode using the Golang language. Next, we need to build a local Hyperledger network to deploy the Chaincode and start tracking the food along the supply chain.