diff --git a/asset-transfer-basic/chaincode-go/assetTransfer.go b/asset-transfer-basic/chaincode-go/assetTransfer.go index 505cf020..bce59dd9 100644 --- a/asset-transfer-basic/chaincode-go/assetTransfer.go +++ b/asset-transfer-basic/chaincode-go/assetTransfer.go @@ -5,212 +5,19 @@ SPDX-License-Identifier: Apache-2.0 package main import ( - "encoding/json" - "fmt" + "log" "github.com/hyperledger/fabric-contract-api-go/contractapi" + "github.com/hyperledger/fabric-samples/asset-transfer-basic/chaincode-go/chaincode" ) -// SmartContract provides functions for managing an Asset -type SmartContract struct { - contractapi.Contract -} - -// Asset describes basic details of what makes up a simple asset -type Asset struct { - ID string `json:"ID"` - Color string `json:"color"` - Size int `json:"size"` - Owner string `json:"owner"` - AppraisedValue int `json:"appraisedValue"` -} - -// QueryResult structure used for handling result of query -type QueryResult struct { - Key string `json:"Key"` - Record *Asset -} - -// InitLedger adds a base set of assets to the ledger -func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error { - assets := []Asset{ - Asset{ID: "asset1", Color: "blue", Size: 5, Owner: "Tomoko", AppraisedValue: 300}, - Asset{ID: "asset2", Color: "red", Size: 5, Owner: "Brad", AppraisedValue: 400}, - Asset{ID: "asset3", Color: "green", Size: 10, Owner: "Jin Soo", AppraisedValue: 500}, - Asset{ID: "asset4", Color: "yellow", Size: 10, Owner: "Max", AppraisedValue: 600}, - Asset{ID: "asset5", Color: "black", Size: 15, Owner: "Adriana", AppraisedValue: 700}, - Asset{ID: "asset6", Color: "white", Size: 15, Owner: "Michel", AppraisedValue: 800}, - } - - for _, asset := range assets { - assetJSON, err := json.Marshal(asset) - if err != nil { - return err - } - - err = ctx.GetStub().PutState(asset.ID, assetJSON) - if err != nil { - return fmt.Errorf("Failed to put to world state. %s", err.Error()) - } - } - - return nil -} - -// CreateAsset issues a new asset to the world state with given details. -func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, id, color, owner string, size, appraisedValue int) error { - exists, err := s.AssetExists(ctx, id) - if err != nil { - return err - } - if exists { - return fmt.Errorf("The asset %s already exists", id) - } - - asset := Asset{ - ID: id, - Color: color, - Size: size, - Owner: owner, - AppraisedValue: appraisedValue, - } - - assetJSON, err := json.Marshal(asset) - if err != nil { - return err - } - - return ctx.GetStub().PutState(id, assetJSON) -} - -// ReadAsset returns the asset stored in the world state with given id. -func (s *SmartContract) ReadAsset(ctx contractapi.TransactionContextInterface, id string) (*Asset, error) { - assetJSON, err := ctx.GetStub().GetState(id) - if err != nil { - return nil, fmt.Errorf("Failed to read from world state. %s", err.Error()) - } - if assetJSON == nil { - return nil, fmt.Errorf("The asset %s does not exist", id) - } - - asset := new(Asset) - err = json.Unmarshal(assetJSON, asset) - if err != nil { - return nil, err - } - - return asset, nil -} - -// UpdateAsset updates an existing asset in the world state with provided parameters. -func (s *SmartContract) UpdateAsset(ctx contractapi.TransactionContextInterface, id, color, owner string, size, appraisedValue int) error { - exists, err := s.AssetExists(ctx, id) - if err != nil { - return err - } - if !exists { - return fmt.Errorf("The asset %s does not exist", id) - } - - // overwritting original asset with new asset - asset := Asset{ - ID: id, - Color: color, - Size: size, - Owner: owner, - AppraisedValue: appraisedValue, - } - - assetJSON, err := json.Marshal(asset) - if err != nil { - return err - } - - return ctx.GetStub().PutState(id, assetJSON) -} - -// DeleteAsset deletes an given asset from the world state. -func (s *SmartContract) DeleteAsset(ctx contractapi.TransactionContextInterface, id string) error { - exists, err := s.AssetExists(ctx, id) - if err != nil { - return err - } - if !exists { - return fmt.Errorf("The asset %s does not exist", id) - } - - return ctx.GetStub().DelState(id) -} - -// AssetExists returns true when asset with given ID exists in world state -func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) { - assetJSON, err := ctx.GetStub().GetState(id) - if err != nil { - return false, fmt.Errorf("Failed to read from world state. %s", err.Error()) - } - - return assetJSON != nil, nil -} - -// TransferAsset updates the owner field of asset with given id in world state. -func (s *SmartContract) TransferAsset(ctx contractapi.TransactionContextInterface, id string, newOwner string) error { - asset, err := s.ReadAsset(ctx, id) - if err != nil { - return err - } - - asset.Owner = newOwner - - assetJSON, err := json.Marshal(asset) - if err != nil { - return err - } - - return ctx.GetStub().PutState(id, assetJSON) -} - -// GetAllAssets returns all assets found in world state -func (s *SmartContract) GetAllAssets(ctx contractapi.TransactionContextInterface) ([]QueryResult, error) { - // range query with empty string for startKey and endKey does an open-ended query of all assets in the chaincode namespace. - resultsIterator, err := ctx.GetStub().GetStateByRange("", "") - - if err != nil { - return nil, err - } - defer resultsIterator.Close() - - results := []QueryResult{} - - for resultsIterator.HasNext() { - queryResponse, err := resultsIterator.Next() - - if err != nil { - return nil, err - } - - asset := new(Asset) - err = json.Unmarshal(queryResponse.Value, asset) - if err != nil { - return nil, err - } - - queryResult := QueryResult{Key: queryResponse.Key, Record: asset} - results = append(results, queryResult) - } - - return results, nil -} - func main() { - - chaincode, err := contractapi.NewChaincode(new(SmartContract)) - + assetChaincode, err := contractapi.NewChaincode(&chaincode.SmartContract{}) if err != nil { - fmt.Printf("Error create asset-transfer-basic chaincode: %s", err.Error()) - return + log.Panicf("Error create asset-transfer-basic chaincode: %v", err) } - if err := chaincode.Start(); err != nil { - fmt.Printf("Error starting asset-transfer-basic chaincode: %s", err.Error()) + if err := assetChaincode.Start(); err != nil { + log.Panicf("Error starting asset-transfer-basic chaincode: %v", err) } } diff --git a/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go b/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go new file mode 100644 index 00000000..862634e8 --- /dev/null +++ b/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go @@ -0,0 +1,193 @@ +package chaincode + +import ( + "encoding/json" + "fmt" + + "github.com/hyperledger/fabric-contract-api-go/contractapi" +) + +// SmartContract provides functions for managing an Asset +type SmartContract struct { + contractapi.Contract +} + +// Asset describes basic details of what makes up a simple asset +type Asset struct { + ID string `json:"ID"` + Color string `json:"color"` + Size int `json:"size"` + Owner string `json:"owner"` + AppraisedValue int `json:"appraisedValue"` +} + +// QueryResult structure used for handling result of query +type QueryResult struct { + Key string `json:"Key"` + Record *Asset +} + +// InitLedger adds a base set of assets to the ledger +func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error { + assets := []Asset{ + {ID: "asset1", Color: "blue", Size: 5, Owner: "Tomoko", AppraisedValue: 300}, + {ID: "asset2", Color: "red", Size: 5, Owner: "Brad", AppraisedValue: 400}, + {ID: "asset3", Color: "green", Size: 10, Owner: "Jin Soo", AppraisedValue: 500}, + {ID: "asset4", Color: "yellow", Size: 10, Owner: "Max", AppraisedValue: 600}, + {ID: "asset5", Color: "black", Size: 15, Owner: "Adriana", AppraisedValue: 700}, + {ID: "asset6", Color: "white", Size: 15, Owner: "Michel", AppraisedValue: 800}, + } + + for _, asset := range assets { + assetJSON, err := json.Marshal(asset) + if err != nil { + return err + } + + err = ctx.GetStub().PutState(asset.ID, assetJSON) + if err != nil { + return fmt.Errorf("failed to put to world state. %v", err) + } + } + + return nil +} + +// CreateAsset issues a new asset to the world state with given details. +func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, id, color, owner string, size, appraisedValue int) error { + exists, err := s.AssetExists(ctx, id) + if err != nil { + return err + } + if exists { + return fmt.Errorf("the asset %s already exists", id) + } + + asset := Asset{ + ID: id, + Color: color, + Size: size, + Owner: owner, + AppraisedValue: appraisedValue, + } + assetJSON, err := json.Marshal(asset) + if err != nil { + return err + } + + return ctx.GetStub().PutState(id, assetJSON) +} + +// ReadAsset returns the asset stored in the world state with given id. +func (s *SmartContract) ReadAsset(ctx contractapi.TransactionContextInterface, id string) (*Asset, error) { + assetJSON, err := ctx.GetStub().GetState(id) + if err != nil { + return nil, fmt.Errorf("failed to read from world state: %v", err) + } + if assetJSON == nil { + return nil, fmt.Errorf("the asset %s does not exist", id) + } + + var asset *Asset + err = json.Unmarshal(assetJSON, &asset) + if err != nil { + return nil, err + } + + return asset, nil +} + +// UpdateAsset updates an existing asset in the world state with provided parameters. +func (s *SmartContract) UpdateAsset(ctx contractapi.TransactionContextInterface, id, color, owner string, size, appraisedValue int) error { + exists, err := s.AssetExists(ctx, id) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("the asset %s does not exist", id) + } + + // overwriting original asset with new asset + asset := Asset{ + ID: id, + Color: color, + Size: size, + Owner: owner, + AppraisedValue: appraisedValue, + } + assetJSON, err := json.Marshal(asset) + if err != nil { + return err + } + + return ctx.GetStub().PutState(id, assetJSON) +} + +// DeleteAsset deletes an given asset from the world state. +func (s *SmartContract) DeleteAsset(ctx contractapi.TransactionContextInterface, id string) error { + exists, err := s.AssetExists(ctx, id) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("the asset %s does not exist", id) + } + + return ctx.GetStub().DelState(id) +} + +// AssetExists returns true when asset with given ID exists in world state +func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) { + assetJSON, err := ctx.GetStub().GetState(id) + if err != nil { + return false, fmt.Errorf("failed to read from world state: %v", err) + } + + return assetJSON != nil, nil +} + +// TransferAsset updates the owner field of asset with given id in world state. +func (s *SmartContract) TransferAsset(ctx contractapi.TransactionContextInterface, id string, newOwner string) error { + asset, err := s.ReadAsset(ctx, id) + if err != nil { + return err + } + + asset.Owner = newOwner + assetJSON, err := json.Marshal(asset) + if err != nil { + return err + } + + return ctx.GetStub().PutState(id, assetJSON) +} + +// GetAllAssets returns all assets found in world state +func (s *SmartContract) GetAllAssets(ctx contractapi.TransactionContextInterface) ([]QueryResult, error) { + // range query with empty string for startKey and endKey does an + // open-ended query of all assets in the chaincode namespace. + resultsIterator, err := ctx.GetStub().GetStateByRange("", "") + if err != nil { + return nil, err + } + defer resultsIterator.Close() + + var results []QueryResult + for resultsIterator.HasNext() { + queryResponse, err := resultsIterator.Next() + if err != nil { + return nil, err + } + + var asset *Asset + err = json.Unmarshal(queryResponse.Value, &asset) + if err != nil { + return nil, err + } + + queryResult := QueryResult{Key: queryResponse.Key, Record: asset} + results = append(results, queryResult) + } + + return results, nil +}