mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 15:35:09 +00:00
Fix asset-transfer-basic/application-gateway-go (#874)
Error handling example used a transaction invocation with the wrong number of arguments and so did not demonstrate the same error condition as other language samples. The error handling code was also not as comprehensive as it should be. Also changed the console output throughout to match the content and format of the Node and Java samples. Signed-off-by: Mark S. Lewis <mark_lewis@uk.ibm.com> Signed-off-by: Mark S. Lewis <mark_lewis@uk.ibm.com>
This commit is contained in:
parent
22e1af4935
commit
a6028cd398
1 changed files with 57 additions and 61 deletions
|
|
@ -13,7 +13,6 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
|
@ -40,8 +39,6 @@ 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()
|
||||
|
|
@ -79,25 +76,12 @@ func main() {
|
|||
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", "asset70", "blue", "5", "Tomoko", "300")
|
||||
if err == nil {
|
||||
panic("******** FAILED to return an error")
|
||||
}
|
||||
|
||||
fmt.Println("*** Successfully caught the 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)
|
||||
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 with gRPC status %v: %s\n", status.Code(err), err)
|
||||
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 with gRPC status %v: %s\n", status.Code(err), err)
|
||||
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() {
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue