diff --git a/asset-transfer-basic/application-gateway-go/assetTransfer.go b/asset-transfer-basic/application-gateway-go/assetTransfer.go index e9ccbe5a..cf489fb6 100755 --- a/asset-transfer-basic/application-gateway-go/assetTransfer.go +++ b/asset-transfer-basic/application-gateway-go/assetTransfer.go @@ -13,7 +13,6 @@ import ( "encoding/json" "errors" "fmt" - "log" "os" "path" "time" @@ -27,21 +26,19 @@ import ( ) const ( - mspID = "Org1MSP" - cryptoPath = "../../test-network/organizations/peerOrganizations/org1.example.com" - certPath = cryptoPath + "/users/User1@org1.example.com/msp/signcerts/cert.pem" - keyPath = cryptoPath + "/users/User1@org1.example.com/msp/keystore/" - tlsCertPath = cryptoPath + "/peers/peer0.org1.example.com/tls/ca.crt" - peerEndpoint = "localhost:7051" - gatewayPeer = "peer0.org1.example.com" + mspID = "Org1MSP" + cryptoPath = "../../test-network/organizations/peerOrganizations/org1.example.com" + certPath = cryptoPath + "/users/User1@org1.example.com/msp/signcerts/cert.pem" + keyPath = cryptoPath + "/users/User1@org1.example.com/msp/keystore/" + tlsCertPath = cryptoPath + "/peers/peer0.org1.example.com/tls/ca.crt" + peerEndpoint = "localhost:7051" + gatewayPeer = "peer0.org1.example.com" ) var now = time.Now() var assetId = fmt.Sprintf("asset%d", now.Unix()*1e3+int64(now.Nanosecond())/1e6) func main() { - log.Println("============ application-golang starts ============") - // The gRPC client connection should be shared by all Gateway connections to this endpoint clientConnection := newGrpcConnection() defer clientConnection.Close() @@ -65,39 +62,26 @@ func main() { } defer gw.Close() - // Override default values for chaincode and channel name as they may differ in testing contexts. - chaincodeName := "basic" - if ccname := os.Getenv("CHAINCODE_NAME"); ccname != "" { - chaincodeName = ccname - } + // Override default values for chaincode and channel name as they may differ in testing contexts. + chaincodeName := "basic" + if ccname := os.Getenv("CHAINCODE_NAME"); ccname != "" { + chaincodeName = ccname + } - channelName := "mychannel" - if cname := os.Getenv("CHANNEL_NAME"); cname != "" { - channelName = cname - } + channelName := "mychannel" + if cname := os.Getenv("CHANNEL_NAME"); cname != "" { + channelName = cname + } network := gw.GetNetwork(channelName) contract := network.GetContract(chaincodeName) - fmt.Println("initLedger:") initLedger(contract) - - fmt.Println("getAllAssets:") getAllAssets(contract) - - fmt.Println("createAsset:") createAsset(contract) - - fmt.Println("readAssetByID:") readAssetByID(contract) - - fmt.Println("transferAssetAsync:") transferAssetAsync(contract) - - fmt.Println("exampleErrorHandling:") exampleErrorHandling(contract) - - log.Println("============ application-golang ends ============") } // newGrpcConnection creates a gRPC connection to the Gateway server. @@ -170,7 +154,7 @@ func newSign() identity.Sign { // This type of transaction would typically only be run once by an application the first time it was started after its // initial deployment. A new version of the chaincode deployed later would likely not need to run an "init" function. func initLedger(contract *client.Contract) { - fmt.Printf("Submit Transaction: InitLedger, function creates the initial set of assets on the ledger \n") + fmt.Printf("\n--> Submit Transaction: InitLedger, function creates the initial set of assets on the ledger \n") _, err := contract.SubmitTransaction("InitLedger") if err != nil { @@ -182,7 +166,7 @@ func initLedger(contract *client.Contract) { // Evaluate a transaction to query ledger state. func getAllAssets(contract *client.Contract) { - fmt.Println("Evaluate Transaction: GetAllAssets, function returns all the current assets on the ledger") + fmt.Println("\n--> Evaluate Transaction: GetAllAssets, function returns all the current assets on the ledger") evaluateResult, err := contract.EvaluateTransaction("GetAllAssets") if err != nil { @@ -195,7 +179,7 @@ func getAllAssets(contract *client.Contract) { // Submit a transaction synchronously, blocking until it has been committed to the ledger. func createAsset(contract *client.Contract) { - fmt.Printf("Submit Transaction: CreateAsset, creates new asset with ID, Color, Size, Owner and AppraisedValue arguments \n") + fmt.Printf("\n--> Submit Transaction: CreateAsset, creates new asset with ID, Color, Size, Owner and AppraisedValue arguments \n") _, err := contract.SubmitTransaction("CreateAsset", assetId, "yellow", "5", "Tom", "1300") if err != nil { @@ -207,7 +191,7 @@ func createAsset(contract *client.Contract) { // Evaluate a transaction by assetID to query ledger state. func readAssetByID(contract *client.Contract) { - fmt.Printf("Evaluate Transaction: ReadAsset, function returns asset attributes\n") + fmt.Printf("\n--> Evaluate Transaction: ReadAsset, function returns asset attributes\n") evaluateResult, err := contract.EvaluateTransaction("ReadAsset", assetId) if err != nil { @@ -221,15 +205,15 @@ func readAssetByID(contract *client.Contract) { // Submit transaction asynchronously, blocking until the transaction has been sent to the orderer, and allowing // this thread to process the chaincode response (e.g. update a UI) without waiting for the commit notification func transferAssetAsync(contract *client.Contract) { - fmt.Printf("Async Submit Transaction: TransferAsset, updates existing asset owner'\n") + fmt.Printf("\n--> Async Submit Transaction: TransferAsset, updates existing asset owner") submitResult, commit, err := contract.SubmitAsync("TransferAsset", client.WithArguments(assetId, "Mark")) if err != nil { panic(fmt.Errorf("failed to submit transaction asynchronously: %w", err)) } - fmt.Printf("Successfully submitted transaction to transfer ownership from %s to Mark. \n", string(submitResult)) - fmt.Println("Waiting for transaction commit.") + fmt.Printf("\n*** Successfully submitted transaction to transfer ownership from %s to Mark. \n", string(submitResult)) + fmt.Println("*** Waiting for transaction commit.") if commitStatus, err := commit.Status(); err != nil { panic(fmt.Errorf("failed to get commit status: %w", err)) @@ -242,32 +226,44 @@ func transferAssetAsync(contract *client.Contract) { // Submit transaction, passing in the wrong number of arguments ,expected to throw an error containing details of any error responses from the smart contract. func exampleErrorHandling(contract *client.Contract) { - fmt.Println("Submit Transaction: UpdateAsset asset70, asset70 does not exist and should return an error") + fmt.Println("\n--> Submit Transaction: UpdateAsset asset70, asset70 does not exist and should return an error") - _, err := contract.SubmitTransaction("UpdateAsset") - if err != nil { - switch err := err.(type) { - case *client.EndorseError: - fmt.Printf("Endorse error with gRPC status %v: %s\n", status.Code(err), err) - case *client.SubmitError: - fmt.Printf("Submit error with gRPC status %v: %s\n", status.Code(err), err) - case *client.CommitStatusError: - if errors.Is(err, context.DeadlineExceeded) { - fmt.Printf("Timeout waiting for transaction %s commit status: %s", err.TransactionID, err) - } else { - fmt.Printf("Error obtaining commit status with gRPC status %v: %s\n", status.Code(err), err) - } - case *client.CommitError: - fmt.Printf("Transaction %s failed to commit with status %d: %s\n", err.TransactionID, int32(err.Code), err) + _, err := contract.SubmitTransaction("UpdateAsset", "asset70", "blue", "5", "Tomoko", "300") + if err == nil { + panic("******** FAILED to return an error") + } + + fmt.Println("*** Successfully caught the error:") + + switch err := err.(type) { + case *client.EndorseError: + fmt.Printf("Endorse error for transaction %s with gRPC status %v: %s\n", err.TransactionID, status.Code(err), err) + case *client.SubmitError: + fmt.Printf("Submit error for transaction %s with gRPC status %v: %s\n", err.TransactionID, status.Code(err), err) + case *client.CommitStatusError: + if errors.Is(err, context.DeadlineExceeded) { + fmt.Printf("Timeout waiting for transaction %s commit status: %s", err.TransactionID, err) + } else { + fmt.Printf("Error obtaining commit status for transaction %s with gRPC status %v: %s\n", err.TransactionID, status.Code(err), err) } + case *client.CommitError: + fmt.Printf("Transaction %s failed to commit with status %d: %s\n", err.TransactionID, int32(err.Code), err) + default: + panic(fmt.Errorf("unexpected error type %T: %w", err, err)) + } - // Any error that originates from a peer or orderer node external to the gateway will have its details - // embedded within the gRPC status error. The following code shows how to extract that. - statusErr := status.Convert(err) - for _, detail := range statusErr.Details() { + // Any error that originates from a peer or orderer node external to the gateway will have its details + // embedded within the gRPC status error. The following code shows how to extract that. + statusErr := status.Convert(err) + + details := statusErr.Details() + if len(details) > 0 { + fmt.Println("Error Details:") + + for _, detail := range details { switch detail := detail.(type) { case *gateway.ErrorDetail: - fmt.Printf("Error from endpoint: %s, mspId: %s, message: %s\n", detail.Address, detail.MspId, detail.Message) + fmt.Printf("- address: %s, mspId: %s, message: %s\n", detail.Address, detail.MspId, detail.Message) } } } @@ -276,7 +272,7 @@ func exampleErrorHandling(contract *client.Contract) { // Format JSON data func formatJSON(data []byte) string { var prettyJSON bytes.Buffer - if err := json.Indent(&prettyJSON, data, " ", ""); err != nil { + if err := json.Indent(&prettyJSON, data, "", " "); err != nil { panic(fmt.Errorf("failed to parse JSON: %w", err)) } return prettyJSON.String()