mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-23 01:55:10 +00:00
Many users raise questions on how to test chaincode. It used to be much easier with the old shim, as they could directly use the old mock stub in the shim. Now that it no longer exists the fabcar example can provide an example of how to test chaincode. Also worth noting is our current directory structure of our Go chaincodes prevents the creation of mocks due to import cycles. This change also pushes the chaincode logic down into a `contract` package. Signed-off-by: Brett Logan <brett.t.logan@ibm.com>
127 lines
3.8 KiB
Go
127 lines
3.8 KiB
Go
package contract
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/hyperledger/fabric-contract-api-go/contractapi"
|
|
)
|
|
|
|
// SmartContract provides functions for managing a car
|
|
type SmartContract struct {
|
|
contractapi.Contract
|
|
}
|
|
|
|
// Car describes basic details of what makes up a car
|
|
type Car struct {
|
|
Make string `json:"make"`
|
|
Model string `json:"model"`
|
|
Colour string `json:"colour"`
|
|
Owner string `json:"owner"`
|
|
}
|
|
|
|
// QueryResult structure used for handling result of query
|
|
type QueryResult struct {
|
|
Key string `json:"Key"`
|
|
Record *Car
|
|
}
|
|
|
|
// InitLedger adds a base set of cars to the ledger
|
|
func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error {
|
|
cars := []Car{
|
|
{Make: "Toyota", Model: "Prius", Colour: "blue", Owner: "Tomoko"},
|
|
{Make: "Ford", Model: "Mustang", Colour: "red", Owner: "Brad"},
|
|
{Make: "Hyundai", Model: "Tucson", Colour: "green", Owner: "Jin Soo"},
|
|
{Make: "Volkswagen", Model: "Passat", Colour: "yellow", Owner: "Max"},
|
|
{Make: "Tesla", Model: "S", Colour: "black", Owner: "Adriana"},
|
|
{Make: "Peugeot", Model: "205", Colour: "purple", Owner: "Michel"},
|
|
{Make: "Chery", Model: "S22L", Colour: "white", Owner: "Aarav"},
|
|
{Make: "Fiat", Model: "Punto", Colour: "violet", Owner: "Pari"},
|
|
{Make: "Tata", Model: "Nano", Colour: "indigo", Owner: "Valeria"},
|
|
{Make: "Holden", Model: "Barina", Colour: "brown", Owner: "Shotaro"},
|
|
}
|
|
|
|
for i, car := range cars {
|
|
carAsBytes, _ := json.Marshal(car)
|
|
key := fmt.Sprintf("CAR%d", i)
|
|
err := ctx.GetStub().PutState(key, carAsBytes)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to put to world state. %v", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CreateCar adds a new car to the world state with given details
|
|
func (s *SmartContract) CreateCar(ctx contractapi.TransactionContextInterface, carNumber string, make string, model string, colour string, owner string) error {
|
|
car := Car{
|
|
Make: make,
|
|
Model: model,
|
|
Colour: colour,
|
|
Owner: owner,
|
|
}
|
|
carAsBytes, err := json.Marshal(car)
|
|
if err != nil {
|
|
return fmt.Errorf("failed marshalling to json: %v", err)
|
|
}
|
|
return ctx.GetStub().PutState(carNumber, carAsBytes)
|
|
}
|
|
|
|
// QueryCar returns the car stored in the world state with given id
|
|
func (s *SmartContract) QueryCar(ctx contractapi.TransactionContextInterface, carNumber string) (*Car, error) {
|
|
carAsBytes, err := ctx.GetStub().GetState(carNumber)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read from world state: %v", err)
|
|
}
|
|
if carAsBytes == nil {
|
|
return nil, fmt.Errorf("%s does not exist", carNumber)
|
|
}
|
|
var car Car
|
|
err = json.Unmarshal(carAsBytes, &car)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &car, nil
|
|
}
|
|
|
|
// QueryAllCars returns all cars found in world state
|
|
func (s *SmartContract) QueryAllCars(ctx contractapi.TransactionContextInterface) ([]QueryResult, error) {
|
|
// Return all cars by using empty startKey and endKey
|
|
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 car *Car
|
|
err = json.Unmarshal(queryResponse.Value, &car)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed marshalling to json: %v", err)
|
|
}
|
|
queryResult := QueryResult{Key: queryResponse.Key, Record: car}
|
|
results = append(results, queryResult)
|
|
}
|
|
return results, nil
|
|
}
|
|
|
|
// ChangeCarOwner updates the owner field of car with given id in world state
|
|
func (s *SmartContract) ChangeCarOwner(ctx contractapi.TransactionContextInterface, carNumber string, newOwner string) error {
|
|
car, err := s.QueryCar(ctx, carNumber)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
car.Owner = newOwner
|
|
carAsBytes, err := json.Marshal(car)
|
|
if err != nil {
|
|
return fmt.Errorf("failed marshalling to json: %v", err)
|
|
}
|
|
return ctx.GetStub().PutState(carNumber, carAsBytes)
|
|
}
|