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"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -27,21 +26,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
mspID = "Org1MSP"
|
mspID = "Org1MSP"
|
||||||
cryptoPath = "../../test-network/organizations/peerOrganizations/org1.example.com"
|
cryptoPath = "../../test-network/organizations/peerOrganizations/org1.example.com"
|
||||||
certPath = cryptoPath + "/users/User1@org1.example.com/msp/signcerts/cert.pem"
|
certPath = cryptoPath + "/users/User1@org1.example.com/msp/signcerts/cert.pem"
|
||||||
keyPath = cryptoPath + "/users/User1@org1.example.com/msp/keystore/"
|
keyPath = cryptoPath + "/users/User1@org1.example.com/msp/keystore/"
|
||||||
tlsCertPath = cryptoPath + "/peers/peer0.org1.example.com/tls/ca.crt"
|
tlsCertPath = cryptoPath + "/peers/peer0.org1.example.com/tls/ca.crt"
|
||||||
peerEndpoint = "localhost:7051"
|
peerEndpoint = "localhost:7051"
|
||||||
gatewayPeer = "peer0.org1.example.com"
|
gatewayPeer = "peer0.org1.example.com"
|
||||||
)
|
)
|
||||||
|
|
||||||
var now = time.Now()
|
var now = time.Now()
|
||||||
var assetId = fmt.Sprintf("asset%d", now.Unix()*1e3+int64(now.Nanosecond())/1e6)
|
var assetId = fmt.Sprintf("asset%d", now.Unix()*1e3+int64(now.Nanosecond())/1e6)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.Println("============ application-golang starts ============")
|
|
||||||
|
|
||||||
// The gRPC client connection should be shared by all Gateway connections to this endpoint
|
// The gRPC client connection should be shared by all Gateway connections to this endpoint
|
||||||
clientConnection := newGrpcConnection()
|
clientConnection := newGrpcConnection()
|
||||||
defer clientConnection.Close()
|
defer clientConnection.Close()
|
||||||
|
|
@ -65,39 +62,26 @@ func main() {
|
||||||
}
|
}
|
||||||
defer gw.Close()
|
defer gw.Close()
|
||||||
|
|
||||||
// Override default values for chaincode and channel name as they may differ in testing contexts.
|
// Override default values for chaincode and channel name as they may differ in testing contexts.
|
||||||
chaincodeName := "basic"
|
chaincodeName := "basic"
|
||||||
if ccname := os.Getenv("CHAINCODE_NAME"); ccname != "" {
|
if ccname := os.Getenv("CHAINCODE_NAME"); ccname != "" {
|
||||||
chaincodeName = ccname
|
chaincodeName = ccname
|
||||||
}
|
}
|
||||||
|
|
||||||
channelName := "mychannel"
|
channelName := "mychannel"
|
||||||
if cname := os.Getenv("CHANNEL_NAME"); cname != "" {
|
if cname := os.Getenv("CHANNEL_NAME"); cname != "" {
|
||||||
channelName = cname
|
channelName = cname
|
||||||
}
|
}
|
||||||
|
|
||||||
network := gw.GetNetwork(channelName)
|
network := gw.GetNetwork(channelName)
|
||||||
contract := network.GetContract(chaincodeName)
|
contract := network.GetContract(chaincodeName)
|
||||||
|
|
||||||
fmt.Println("initLedger:")
|
|
||||||
initLedger(contract)
|
initLedger(contract)
|
||||||
|
|
||||||
fmt.Println("getAllAssets:")
|
|
||||||
getAllAssets(contract)
|
getAllAssets(contract)
|
||||||
|
|
||||||
fmt.Println("createAsset:")
|
|
||||||
createAsset(contract)
|
createAsset(contract)
|
||||||
|
|
||||||
fmt.Println("readAssetByID:")
|
|
||||||
readAssetByID(contract)
|
readAssetByID(contract)
|
||||||
|
|
||||||
fmt.Println("transferAssetAsync:")
|
|
||||||
transferAssetAsync(contract)
|
transferAssetAsync(contract)
|
||||||
|
|
||||||
fmt.Println("exampleErrorHandling:")
|
|
||||||
exampleErrorHandling(contract)
|
exampleErrorHandling(contract)
|
||||||
|
|
||||||
log.Println("============ application-golang ends ============")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// newGrpcConnection creates a gRPC connection to the Gateway server.
|
// 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
|
// 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.
|
// initial deployment. A new version of the chaincode deployed later would likely not need to run an "init" function.
|
||||||
func initLedger(contract *client.Contract) {
|
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")
|
_, err := contract.SubmitTransaction("InitLedger")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -182,7 +166,7 @@ func initLedger(contract *client.Contract) {
|
||||||
|
|
||||||
// Evaluate a transaction to query ledger state.
|
// Evaluate a transaction to query ledger state.
|
||||||
func getAllAssets(contract *client.Contract) {
|
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")
|
evaluateResult, err := contract.EvaluateTransaction("GetAllAssets")
|
||||||
if err != nil {
|
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.
|
// Submit a transaction synchronously, blocking until it has been committed to the ledger.
|
||||||
func createAsset(contract *client.Contract) {
|
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")
|
_, err := contract.SubmitTransaction("CreateAsset", assetId, "yellow", "5", "Tom", "1300")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -207,7 +191,7 @@ func createAsset(contract *client.Contract) {
|
||||||
|
|
||||||
// Evaluate a transaction by assetID to query ledger state.
|
// Evaluate a transaction by assetID to query ledger state.
|
||||||
func readAssetByID(contract *client.Contract) {
|
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)
|
evaluateResult, err := contract.EvaluateTransaction("ReadAsset", assetId)
|
||||||
if err != nil {
|
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
|
// 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
|
// this thread to process the chaincode response (e.g. update a UI) without waiting for the commit notification
|
||||||
func transferAssetAsync(contract *client.Contract) {
|
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"))
|
submitResult, commit, err := contract.SubmitAsync("TransferAsset", client.WithArguments(assetId, "Mark"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Errorf("failed to submit transaction asynchronously: %w", err))
|
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.Printf("\n*** Successfully submitted transaction to transfer ownership from %s to Mark. \n", string(submitResult))
|
||||||
fmt.Println("Waiting for transaction commit.")
|
fmt.Println("*** Waiting for transaction commit.")
|
||||||
|
|
||||||
if commitStatus, err := commit.Status(); err != nil {
|
if commitStatus, err := commit.Status(); err != nil {
|
||||||
panic(fmt.Errorf("failed to get commit status: %w", err))
|
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.
|
// 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) {
|
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")
|
_, err := contract.SubmitTransaction("UpdateAsset", "asset70", "blue", "5", "Tomoko", "300")
|
||||||
if err != nil {
|
if err == nil {
|
||||||
switch err := err.(type) {
|
panic("******** FAILED to return an error")
|
||||||
case *client.EndorseError:
|
}
|
||||||
fmt.Printf("Endorse error with gRPC status %v: %s\n", status.Code(err), err)
|
|
||||||
case *client.SubmitError:
|
fmt.Println("*** Successfully caught the error:")
|
||||||
fmt.Printf("Submit error with gRPC status %v: %s\n", status.Code(err), err)
|
|
||||||
case *client.CommitStatusError:
|
switch err := err.(type) {
|
||||||
if errors.Is(err, context.DeadlineExceeded) {
|
case *client.EndorseError:
|
||||||
fmt.Printf("Timeout waiting for transaction %s commit status: %s", err.TransactionID, err)
|
fmt.Printf("Endorse error for transaction %s with gRPC status %v: %s\n", err.TransactionID, status.Code(err), err)
|
||||||
} else {
|
case *client.SubmitError:
|
||||||
fmt.Printf("Error obtaining commit status 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:
|
||||||
case *client.CommitError:
|
if errors.Is(err, context.DeadlineExceeded) {
|
||||||
fmt.Printf("Transaction %s failed to commit with status %d: %s\n", err.TransactionID, int32(err.Code), err)
|
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
|
// 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.
|
// embedded within the gRPC status error. The following code shows how to extract that.
|
||||||
statusErr := status.Convert(err)
|
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) {
|
switch detail := detail.(type) {
|
||||||
case *gateway.ErrorDetail:
|
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
|
// Format JSON data
|
||||||
func formatJSON(data []byte) string {
|
func formatJSON(data []byte) string {
|
||||||
var prettyJSON bytes.Buffer
|
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))
|
panic(fmt.Errorf("failed to parse JSON: %w", err))
|
||||||
}
|
}
|
||||||
return prettyJSON.String()
|
return prettyJSON.String()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue