Module 5: Advanced Topics and Use Cases

5.3 Real-World Applications and Case Studies

Hyperledger Fabric has been deployed across various industries to solve real-world business problems. This section explores several case studies and applications that demonstrate the practical value of Hyperledger Fabric.

Supply Chain Management

Supply chain management is one of the most prominent use cases for blockchain technology, and Hyperledger Fabric provides an ideal platform for implementing supply chain solutions.

IBM Food Trust

IBM Food Trust is a production blockchain network built on Hyperledger Fabric that connects participants across the food supply chain through a permissioned, permanent, and shared record of food system data.

Key Features: - Complete food traceability from farm to consumer - Improved food safety through rapid identification of contamination sources - Reduced waste by optimizing the supply chain - Enhanced sustainability through transparent sourcing

Technical Implementation: - Multi-organization network with growers, processors, distributors, retailers, and regulators - Private data collections for sensitive business information - Smart contracts for automated compliance and certification - Integration with IoT devices for real-time tracking

Architecture Diagram:

+-------------------+     +-------------------+     +-------------------+
|                   |     |                   |     |                   |
|     Producers     |     |    Processors     |     |    Distributors   |
|                   |     |                   |     |                   |
+--------+----------+     +--------+----------+     +--------+----------+
         |                         |                         |
         |                         |                         |
         v                         v                         v
+-------------------------------------------------------------------+
|                                                                   |
|                     Hyperledger Fabric Network                    |
|                                                                   |
+-------------------------------------------------------------------+
         ^                         ^                         ^
         |                         |                         |
         |                         |                         |
+--------+----------+     +--------+----------+     +--------+----------+
|                   |     |                   |     |                   |
|     Retailers     |     |    Regulators     |     |    Consumers     |
|                   |     |                   |     |                   |
+-------------------+     +-------------------+     +-------------------+

Sample Chaincode for Product Tracking:

package main

import (
    "encoding/json"
    "fmt"
    "time"

    "github.com/hyperledger/fabric-contract-api-go/contractapi"
)

// FoodProduct represents a food product in the supply chain
type FoodProduct struct {
    ID              string    `json:"id"`
    ProductType     string    `json:"productType"`
    Producer        string    `json:"producer"`
    ProductionDate  time.Time `json:"productionDate"`
    ExpirationDate  time.Time `json:"expirationDate"`
    BatchNumber     string    `json:"batchNumber"`
    CurrentLocation string    `json:"currentLocation"`
    Status          string    `json:"status"`
    CertificateIDs  []string  `json:"certificateIds"`
    History         []Event   `json:"history"`
}

// Event represents a supply chain event
type Event struct {
    Timestamp time.Time `json:"timestamp"`
    Location  string    `json:"location"`
    Action    string    `json:"action"`
    Actor     string    `json:"actor"`
    Details   string    `json:"details"`
}

// Certificate represents a certification or compliance document
type Certificate struct {
    ID           string    `json:"id"`
    Type         string    `json:"type"`
    Issuer       string    `json:"issuer"`
    IssuedTo     string    `json:"issuedTo"`
    IssuedDate   time.Time `json:"issuedDate"`
    ExpiryDate   time.Time `json:"expiryDate"`
    DocumentHash string    `json:"documentHash"`
}

// SmartContract provides functions for managing the food supply chain
type SmartContract struct {
    contractapi.Contract
}

// CreateProduct creates a new food product in the ledger
func (s *SmartContract) CreateProduct(ctx contractapi.TransactionContextInterface, id string, productType string, producer string, productionDate string, expirationDate string, batchNumber string) error {
    exists, err := s.ProductExists(ctx, id)
    if err != nil {
        return err
    }
    if exists {
        return fmt.Errorf("the product %s already exists", id)
    }

    // Parse dates
    prodDate, err := time.Parse(time.RFC3339, productionDate)
    if err != nil {
        return fmt.Errorf("invalid production date format: %v", err)
    }

    expDate, err := time.Parse(time.RFC3339, expirationDate)
    if err != nil {
        return fmt.Errorf("invalid expiration date format: %v", err)
    }

    // Get client identity for the producer
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Create the product
    product := FoodProduct{
        ID:              id,
        ProductType:     productType,
        Producer:        producer,
        ProductionDate:  prodDate,
        ExpirationDate:  expDate,
        BatchNumber:     batchNumber,
        CurrentLocation: producer,
        Status:          "PRODUCED",
        CertificateIDs:  []string{},
        History: []Event{
            {
                Timestamp: time.Now(),
                Location:  producer,
                Action:    "PRODUCED",
                Actor:     clientID,
                Details:   fmt.Sprintf("Product %s was produced", id),
            },
        },
    }

    productJSON, err := json.Marshal(product)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(id, productJSON)
}

// ReadProduct returns the product stored in the world state with given id
func (s *SmartContract) ReadProduct(ctx contractapi.TransactionContextInterface, id string) (*FoodProduct, error) {
    productJSON, err := ctx.GetStub().GetState(id)
    if err != nil {
        return nil, fmt.Errorf("failed to read from world state: %v", err)
    }
    if productJSON == nil {
        return nil, fmt.Errorf("the product %s does not exist", id)
    }

    var product FoodProduct
    err = json.Unmarshal(productJSON, &product)
    if err != nil {
        return nil, err
    }

    return &product, nil
}

// UpdateProductLocation updates the current location of a product
func (s *SmartContract) UpdateProductLocation(ctx contractapi.TransactionContextInterface, id string, newLocation string) error {
    product, err := s.ReadProduct(ctx, id)
    if err != nil {
        return err
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Update the product location
    product.CurrentLocation = newLocation

    // Add event to history
    product.History = append(product.History, Event{
        Timestamp: time.Now(),
        Location:  newLocation,
        Action:    "LOCATION_UPDATE",
        Actor:     clientID,
        Details:   fmt.Sprintf("Product moved to %s", newLocation),
    })

    productJSON, err := json.Marshal(product)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(id, productJSON)
}

// UpdateProductStatus updates the status of a product
func (s *SmartContract) UpdateProductStatus(ctx contractapi.TransactionContextInterface, id string, newStatus string) error {
    product, err := s.ReadProduct(ctx, id)
    if err != nil {
        return err
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Update the product status
    product.Status = newStatus

    // Add event to history
    product.History = append(product.History, Event{
        Timestamp: time.Now(),
        Location:  product.CurrentLocation,
        Action:    "STATUS_UPDATE",
        Actor:     clientID,
        Details:   fmt.Sprintf("Product status changed to %s", newStatus),
    })

    productJSON, err := json.Marshal(product)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(id, productJSON)
}

// AddCertificate adds a new certificate to the ledger
func (s *SmartContract) AddCertificate(ctx contractapi.TransactionContextInterface, id string, certType string, issuer string, issuedTo string, issuedDate string, expiryDate string, documentHash string) error {
    exists, err := s.CertificateExists(ctx, id)
    if err != nil {
        return err
    }
    if exists {
        return fmt.Errorf("the certificate %s already exists", id)
    }

    // Parse dates
    issueDate, err := time.Parse(time.RFC3339, issuedDate)
    if err != nil {
        return fmt.Errorf("invalid issued date format: %v", err)
    }

    expDate, err := time.Parse(time.RFC3339, expiryDate)
    if err != nil {
        return fmt.Errorf("invalid expiry date format: %v", err)
    }

    // Create the certificate
    certificate := Certificate{
        ID:           id,
        Type:         certType,
        Issuer:       issuer,
        IssuedTo:     issuedTo,
        IssuedDate:   issueDate,
        ExpiryDate:   expDate,
        DocumentHash: documentHash,
    }

    certificateJSON, err := json.Marshal(certificate)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(fmt.Sprintf("CERT_%s", id), certificateJSON)
}

// LinkCertificateToProduct links a certificate to a product
func (s *SmartContract) LinkCertificateToProduct(ctx contractapi.TransactionContextInterface, productID string, certificateID string) error {
    // Check if product exists
    product, err := s.ReadProduct(ctx, productID)
    if err != nil {
        return err
    }

    // Check if certificate exists
    exists, err := s.CertificateExists(ctx, certificateID)
    if err != nil {
        return err
    }
    if !exists {
        return fmt.Errorf("the certificate %s does not exist", certificateID)
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Add certificate to product
    product.CertificateIDs = append(product.CertificateIDs, certificateID)

    // Add event to history
    product.History = append(product.History, Event{
        Timestamp: time.Now(),
        Location:  product.CurrentLocation,
        Action:    "CERTIFICATE_LINKED",
        Actor:     clientID,
        Details:   fmt.Sprintf("Certificate %s linked to product", certificateID),
    })

    productJSON, err := json.Marshal(product)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(productID, productJSON)
}

// GetProductHistory returns the history of a product
func (s *SmartContract) GetProductHistory(ctx contractapi.TransactionContextInterface, id string) ([]Event, error) {
    product, err := s.ReadProduct(ctx, id)
    if err != nil {
        return nil, err
    }

    return product.History, nil
}

// QueryProductsByType returns all products of a specific type
func (s *SmartContract) QueryProductsByType(ctx contractapi.TransactionContextInterface, productType string) ([]*FoodProduct, error) {
    queryString := fmt.Sprintf(`{"selector":{"productType":"%s"}}`, productType)

    return s.getQueryResultForQueryString(ctx, queryString)
}

// QueryProductsByProducer returns all products from a specific producer
func (s *SmartContract) QueryProductsByProducer(ctx contractapi.TransactionContextInterface, producer string) ([]*FoodProduct, error) {
    queryString := fmt.Sprintf(`{"selector":{"producer":"%s"}}`, producer)

    return s.getQueryResultForQueryString(ctx, queryString)
}

// QueryProductsByStatus returns all products with a specific status
func (s *SmartContract) QueryProductsByStatus(ctx contractapi.TransactionContextInterface, status string) ([]*FoodProduct, error) {
    queryString := fmt.Sprintf(`{"selector":{"status":"%s"}}`, status)

    return s.getQueryResultForQueryString(ctx, queryString)
}

// ProductExists returns true when product with given ID exists in world state
func (s *SmartContract) ProductExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) {
    productJSON, err := ctx.GetStub().GetState(id)
    if err != nil {
        return false, fmt.Errorf("failed to read from world state: %v", err)
    }

    return productJSON != nil, nil
}

// CertificateExists returns true when certificate with given ID exists in world state
func (s *SmartContract) CertificateExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) {
    certificateJSON, err := ctx.GetStub().GetState(fmt.Sprintf("CERT_%s", id))
    if err != nil {
        return false, fmt.Errorf("failed to read from world state: %v", err)
    }

    return certificateJSON != nil, nil
}

// Helper function to get client identity
func (s *SmartContract) getClientIdentity(ctx contractapi.TransactionContextInterface) (string, error) {
    clientID, err := ctx.GetClientIdentity().GetID()
    if err != nil {
        return "", fmt.Errorf("failed to get client identity: %v", err)
    }

    return clientID, nil
}

// Helper function for rich queries
func (s *SmartContract) getQueryResultForQueryString(ctx contractapi.TransactionContextInterface, queryString string) ([]*FoodProduct, error) {
    resultsIterator, err := ctx.GetStub().GetQueryResult(queryString)
    if err != nil {
        return nil, err
    }
    defer resultsIterator.Close()

    var products []*FoodProduct
    for resultsIterator.HasNext() {
        queryResponse, err := resultsIterator.Next()
        if err != nil {
            return nil, err
        }

        var product FoodProduct
        err = json.Unmarshal(queryResponse.Value, &product)
        if err != nil {
            return nil, err
        }
        products = append(products, &product)
    }

    return products, nil
}

func main() {
    chaincode, err := contractapi.NewChaincode(&SmartContract{})
    if err != nil {
        fmt.Printf("Error creating food supply chain chaincode: %v\n", err)
        return
    }

    if err := chaincode.Start(); err != nil {
        fmt.Printf("Error starting food supply chain chaincode: %v\n", err)
    }
}

Trade Finance

Trade finance is another area where Hyperledger Fabric has been successfully deployed to streamline processes, reduce fraud, and increase transparency.

we.trade

we.trade is a blockchain-based platform built on Hyperledger Fabric that simplifies international trade by connecting banks, buyers, and sellers.

Key Features: - Digital trade contracts with automated enforcement - Bank payment undertaking (BPU) to reduce risk - Real-time tracking of trade transactions - Simplified KYC and regulatory compliance

Technical Implementation: - Multi-bank consortium network - Smart contracts for trade agreements and payment obligations - Integration with existing banking systems - Regulatory reporting capabilities

Process Flow:

  1. Buyer and seller negotiate terms and create a digital trade agreement
  2. Buyer's bank issues a BPU, guaranteeing payment
  3. Seller ships goods and uploads proof of shipment
  4. Smart contract verifies conditions are met
  5. Payment is automatically triggered based on agreed terms

Sample Chaincode for Letter of Credit:

package main

import (
    "encoding/json"
    "fmt"
    "time"

    "github.com/hyperledger/fabric-contract-api-go/contractapi"
)

// LetterOfCredit represents a letter of credit in trade finance
type LetterOfCredit struct {
    ID                 string    `json:"id"`
    Applicant          string    `json:"applicant"`          // Buyer
    ApplicantBank      string    `json:"applicantBank"`      // Buyer's bank
    Beneficiary        string    `json:"beneficiary"`        // Seller
    BeneficiaryBank    string    `json:"beneficiaryBank"`    // Seller's bank
    IssuanceDate       time.Time `json:"issuanceDate"`
    ExpiryDate         time.Time `json:"expiryDate"`
    Amount             float64   `json:"amount"`
    Currency           string    `json:"currency"`
    DocumentsRequired  []string  `json:"documentsRequired"`
    Status             string    `json:"status"`
    ShipmentDate       time.Time `json:"shipmentDate"`
    DocumentsSubmitted []string  `json:"documentsSubmitted"`
    History            []Event   `json:"history"`
}

// Event represents a trade finance event
type Event struct {
    Timestamp time.Time `json:"timestamp"`
    Action    string    `json:"action"`
    Actor     string    `json:"actor"`
    Details   string    `json:"details"`
}

// Document represents a trade document
type Document struct {
    ID          string    `json:"id"`
    Type        string    `json:"type"`
    IssuedBy    string    `json:"issuedBy"`
    IssuedDate  time.Time `json:"issuedDate"`
    Description string    `json:"description"`
    FileHash    string    `json:"fileHash"`
    Status      string    `json:"status"`
}

// SmartContract provides functions for managing trade finance
type SmartContract struct {
    contractapi.Contract
}

// IssueLOC issues a new letter of credit
func (s *SmartContract) IssueLOC(ctx contractapi.TransactionContextInterface, id string, applicant string, applicantBank string, beneficiary string, beneficiaryBank string, issuanceDate string, expiryDate string, amount float64, currency string, documentsRequired string) error {
    exists, err := s.LOCExists(ctx, id)
    if err != nil {
        return err
    }
    if exists {
        return fmt.Errorf("the letter of credit %s already exists", id)
    }

    // Parse dates
    issueDate, err := time.Parse(time.RFC3339, issuanceDate)
    if err != nil {
        return fmt.Errorf("invalid issuance date format: %v", err)
    }

    expDate, err := time.Parse(time.RFC3339, expiryDate)
    if err != nil {
        return fmt.Errorf("invalid expiry date format: %v", err)
    }

    // Parse documents required
    var docs []string
    err = json.Unmarshal([]byte(documentsRequired), &docs)
    if err != nil {
        return fmt.Errorf("invalid documents required format: %v", err)
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Verify that the client is from the applicant bank
    clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
    if err != nil {
        return fmt.Errorf("failed to get client MSPID: %v", err)
    }

    if clientMSPID != applicantBank {
        return fmt.Errorf("client from %s is not authorized to issue LOC for %s", clientMSPID, applicantBank)
    }

    // Create the letter of credit
    loc := LetterOfCredit{
        ID:                id,
        Applicant:         applicant,
        ApplicantBank:     applicantBank,
        Beneficiary:       beneficiary,
        BeneficiaryBank:   beneficiaryBank,
        IssuanceDate:      issueDate,
        ExpiryDate:        expDate,
        Amount:            amount,
        Currency:          currency,
        DocumentsRequired: docs,
        Status:            "ISSUED",
        History: []Event{
            {
                Timestamp: time.Now(),
                Action:    "ISSUED",
                Actor:     clientID,
                Details:   fmt.Sprintf("Letter of Credit %s was issued", id),
            },
        },
    }

    locJSON, err := json.Marshal(loc)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(id, locJSON)
}

// ReadLOC returns the letter of credit stored in the world state with given id
func (s *SmartContract) ReadLOC(ctx contractapi.TransactionContextInterface, id string) (*LetterOfCredit, error) {
    locJSON, err := ctx.GetStub().GetState(id)
    if err != nil {
        return nil, fmt.Errorf("failed to read from world state: %v", err)
    }
    if locJSON == nil {
        return nil, fmt.Errorf("the letter of credit %s does not exist", id)
    }

    var loc LetterOfCredit
    err = json.Unmarshal(locJSON, &loc)
    if err != nil {
        return nil, err
    }

    return &loc, nil
}

// SubmitDocument submits a trade document for a letter of credit
func (s *SmartContract) SubmitDocument(ctx contractapi.TransactionContextInterface, locID string, docID string, docType string, issuedBy string, issuedDate string, description string, fileHash string) error {
    // Check if LOC exists
    loc, err := s.ReadLOC(ctx, locID)
    if err != nil {
        return err
    }

    // Check if document is required
    isRequired := false
    for _, requiredDoc := range loc.DocumentsRequired {
        if requiredDoc == docType {
            isRequired = true
            break
        }
    }

    if !isRequired {
        return fmt.Errorf("document type %s is not required for this LOC", docType)
    }

    // Parse date
    issueDate, err := time.Parse(time.RFC3339, issuedDate)
    if err != nil {
        return fmt.Errorf("invalid issued date format: %v", err)
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Create the document
    document := Document{
        ID:          docID,
        Type:        docType,
        IssuedBy:    issuedBy,
        IssuedDate:  issueDate,
        Description: description,
        FileHash:    fileHash,
        Status:      "SUBMITTED",
    }

    documentJSON, err := json.Marshal(document)
    if err != nil {
        return err
    }

    // Store the document
    err = ctx.GetStub().PutState(fmt.Sprintf("DOC_%s", docID), documentJSON)
    if err != nil {
        return fmt.Errorf("failed to put document in world state: %v", err)
    }

    // Update the LOC
    loc.DocumentsSubmitted = append(loc.DocumentsSubmitted, docID)

    // Add event to history
    loc.History = append(loc.History, Event{
        Timestamp: time.Now(),
        Action:    "DOCUMENT_SUBMITTED",
        Actor:     clientID,
        Details:   fmt.Sprintf("Document %s of type %s was submitted", docID, docType),
    })

    // Check if all required documents are submitted
    if len(loc.DocumentsSubmitted) >= len(loc.DocumentsRequired) {
        loc.Status = "DOCUMENTS_RECEIVED"
    }

    locJSON, err := json.Marshal(loc)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(locID, locJSON)
}

// VerifyDocuments verifies the submitted documents for a letter of credit
func (s *SmartContract) VerifyDocuments(ctx contractapi.TransactionContextInterface, locID string, approved bool, comments string) error {
    // Check if LOC exists
    loc, err := s.ReadLOC(ctx, locID)
    if err != nil {
        return err
    }

    // Check if documents have been submitted
    if loc.Status != "DOCUMENTS_RECEIVED" {
        return fmt.Errorf("documents have not been fully submitted yet")
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Verify that the client is from the applicant bank
    clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
    if err != nil {
        return fmt.Errorf("failed to get client MSPID: %v", err)
    }

    if clientMSPID != loc.ApplicantBank {
        return fmt.Errorf("client from %s is not authorized to verify documents for %s", clientMSPID, loc.ApplicantBank)
    }

    // Update the LOC status based on verification result
    if approved {
        loc.Status = "APPROVED"
    } else {
        loc.Status = "REJECTED"
    }

    // Add event to history
    loc.History = append(loc.History, Event{
        Timestamp: time.Now(),
        Action:    fmt.Sprintf("DOCUMENTS_%s", loc.Status),
        Actor:     clientID,
        Details:   comments,
    })

    locJSON, err := json.Marshal(loc)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(locID, locJSON)
}

// MakePayment processes payment for an approved letter of credit
func (s *SmartContract) MakePayment(ctx contractapi.TransactionContextInterface, locID string, paymentReference string) error {
    // Check if LOC exists
    loc, err := s.ReadLOC(ctx, locID)
    if err != nil {
        return err
    }

    // Check if LOC is approved
    if loc.Status != "APPROVED" {
        return fmt.Errorf("letter of credit is not approved for payment")
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Verify that the client is from the applicant bank
    clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
    if err != nil {
        return fmt.Errorf("failed to get client MSPID: %v", err)
    }

    if clientMSPID != loc.ApplicantBank {
        return fmt.Errorf("client from %s is not authorized to make payment for %s", clientMSPID, loc.ApplicantBank)
    }

    // Update the LOC status
    loc.Status = "PAID"

    // Add event to history
    loc.History = append(loc.History, Event{
        Timestamp: time.Now(),
        Action:    "PAYMENT_MADE",
        Actor:     clientID,
        Details:   fmt.Sprintf("Payment made with reference %s", paymentReference),
    })

    locJSON, err := json.Marshal(loc)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(locID, locJSON)
}

// QueryLOCsByApplicant returns all letters of credit for a specific applicant
func (s *SmartContract) QueryLOCsByApplicant(ctx contractapi.TransactionContextInterface, applicant string) ([]*LetterOfCredit, error) {
    queryString := fmt.Sprintf(`{"selector":{"applicant":"%s"}}`, applicant)

    return s.getQueryResultForQueryString(ctx, queryString)
}

// QueryLOCsByBeneficiary returns all letters of credit for a specific beneficiary
func (s *SmartContract) QueryLOCsByBeneficiary(ctx contractapi.TransactionContextInterface, beneficiary string) ([]*LetterOfCredit, error) {
    queryString := fmt.Sprintf(`{"selector":{"beneficiary":"%s"}}`, beneficiary)

    return s.getQueryResultForQueryString(ctx, queryString)
}

// QueryLOCsByStatus returns all letters of credit with a specific status
func (s *SmartContract) QueryLOCsByStatus(ctx contractapi.TransactionContextInterface, status string) ([]*LetterOfCredit, error) {
    queryString := fmt.Sprintf(`{"selector":{"status":"%s"}}`, status)

    return s.getQueryResultForQueryString(ctx, queryString)
}

// LOCExists returns true when letter of credit with given ID exists in world state
func (s *SmartContract) LOCExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) {
    locJSON, err := ctx.GetStub().GetState(id)
    if err != nil {
        return false, fmt.Errorf("failed to read from world state: %v", err)
    }

    return locJSON != nil, nil
}

// Helper function to get client identity
func (s *SmartContract) getClientIdentity(ctx contractapi.TransactionContextInterface) (string, error) {
    clientID, err := ctx.GetClientIdentity().GetID()
    if err != nil {
        return "", fmt.Errorf("failed to get client identity: %v", err)
    }

    return clientID, nil
}

// Helper function for rich queries
func (s *SmartContract) getQueryResultForQueryString(ctx contractapi.TransactionContextInterface, queryString string) ([]*LetterOfCredit, error) {
    resultsIterator, err := ctx.GetStub().GetQueryResult(queryString)
    if err != nil {
        return nil, err
    }
    defer resultsIterator.Close()

    var locs []*LetterOfCredit
    for resultsIterator.HasNext() {
        queryResponse, err := resultsIterator.Next()
        if err != nil {
            return nil, err
        }

        var loc LetterOfCredit
        err = json.Unmarshal(queryResponse.Value, &loc)
        if err != nil {
            return nil, err
        }
        locs = append(locs, &loc)
    }

    return locs, nil
}

func main() {
    chaincode, err := contractapi.NewChaincode(&SmartContract{})
    if err != nil {
        fmt.Printf("Error creating trade finance chaincode: %v\n", err)
        return
    }

    if err := chaincode.Start(); err != nil {
        fmt.Printf("Error starting trade finance chaincode: %v\n", err)
    }
}

Healthcare

Hyperledger Fabric is being used in healthcare to improve data sharing while maintaining privacy and compliance with regulations.

MiPasa

MiPasa is a blockchain-based platform built on Hyperledger Fabric that enables secure sharing of COVID-19 data across healthcare organizations.

Key Features: - Secure sharing of anonymized health data - Data verification and validation - Privacy-preserving analytics - Integration with existing healthcare systems

Technical Implementation: - Multi-organization network with healthcare providers, researchers, and government agencies - Private data collections for sensitive health information - Zero-knowledge proofs for privacy-preserving analytics - Integration with data analytics tools

Sample Chaincode for Health Data Sharing:

package main

import (
    "encoding/json"
    "fmt"
    "time"

    "github.com/hyperledger/fabric-contract-api-go/contractapi"
)

// HealthDataRecord represents a health data record
type HealthDataRecord struct {
    ID                string    `json:"id"`
    PatientID         string    `json:"patientId"`
    RecordType        string    `json:"recordType"`
    Provider          string    `json:"provider"`
    CreationDate      time.Time `json:"creationDate"`
    LastModifiedDate  time.Time `json:"lastModifiedDate"`
    DataHash          string    `json:"dataHash"`
    AccessPermissions []string  `json:"accessPermissions"`
    Status            string    `json:"status"`
    History           []Event   `json:"history"`
}

// Event represents a health data event
type Event struct {
    Timestamp time.Time `json:"timestamp"`
    Action    string    `json:"action"`
    Actor     string    `json:"actor"`
    Details   string    `json:"details"`
}

// ConsentRecord represents a patient consent record
type ConsentRecord struct {
    ID           string    `json:"id"`
    PatientID    string    `json:"patientId"`
    OrganizationID string  `json:"organizationId"`
    Purpose      string    `json:"purpose"`
    GrantedDate  time.Time `json:"grantedDate"`
    ExpiryDate   time.Time `json:"expiryDate"`
    Status       string    `json:"status"`
}

// SmartContract provides functions for managing health data
type SmartContract struct {
    contractapi.Contract
}

// CreateHealthRecord creates a new health data record
func (s *SmartContract) CreateHealthRecord(ctx contractapi.TransactionContextInterface, id string, patientID string, recordType string, provider string, dataHash string) error {
    exists, err := s.HealthRecordExists(ctx, id)
    if err != nil {
        return err
    }
    if exists {
        return fmt.Errorf("the health record %s already exists", id)
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Verify that the client is from the provider organization
    clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
    if err != nil {
        return fmt.Errorf("failed to get client MSPID: %v", err)
    }

    if clientMSPID != provider {
        return fmt.Errorf("client from %s is not authorized to create records for %s", clientMSPID, provider)
    }

    // Check if consent exists for this patient and provider
    consentExists, err := s.checkConsent(ctx, patientID, provider)
    if err != nil {
        return err
    }
    if !consentExists {
        return fmt.Errorf("no valid consent exists for patient %s and provider %s", patientID, provider)
    }

    // Create the health record
    now := time.Now()
    record := HealthDataRecord{
        ID:                id,
        PatientID:         patientID,
        RecordType:        recordType,
        Provider:          provider,
        CreationDate:      now,
        LastModifiedDate:  now,
        DataHash:          dataHash,
        AccessPermissions: []string{provider},
        Status:            "ACTIVE",
        History: []Event{
            {
                Timestamp: now,
                Action:    "CREATED",
                Actor:     clientID,
                Details:   fmt.Sprintf("Health record %s was created", id),
            },
        },
    }

    recordJSON, err := json.Marshal(record)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(id, recordJSON)
}

// ReadHealthRecord returns the health record stored in the world state with given id
func (s *SmartContract) ReadHealthRecord(ctx contractapi.TransactionContextInterface, id string) (*HealthDataRecord, error) {
    recordJSON, err := ctx.GetStub().GetState(id)
    if err != nil {
        return nil, fmt.Errorf("failed to read from world state: %v", err)
    }
    if recordJSON == nil {
        return nil, fmt.Errorf("the health record %s does not exist", id)
    }

    var record HealthDataRecord
    err = json.Unmarshal(recordJSON, &record)
    if err != nil {
        return nil, err
    }

    // Check if the client has permission to access this record
    clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
    if err != nil {
        return nil, fmt.Errorf("failed to get client MSPID: %v", err)
    }

    hasAccess := false
    for _, org := range record.AccessPermissions {
        if org == clientMSPID {
            hasAccess = true
            break
        }
    }

    if !hasAccess {
        return nil, fmt.Errorf("client from %s is not authorized to access this record", clientMSPID)
    }

    return &record, nil
}

// UpdateHealthRecord updates an existing health record
func (s *SmartContract) UpdateHealthRecord(ctx contractapi.TransactionContextInterface, id string, dataHash string) error {
    record, err := s.ReadHealthRecord(ctx, id)
    if err != nil {
        return err
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Verify that the client is from the provider organization
    clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
    if err != nil {
        return fmt.Errorf("failed to get client MSPID: %v", err)
    }

    if clientMSPID != record.Provider {
        return fmt.Errorf("client from %s is not authorized to update records for %s", clientMSPID, record.Provider)
    }

    // Update the record
    record.DataHash = dataHash
    record.LastModifiedDate = time.Now()

    // Add event to history
    record.History = append(record.History, Event{
        Timestamp: time.Now(),
        Action:    "UPDATED",
        Actor:     clientID,
        Details:   fmt.Sprintf("Health record %s was updated", id),
    })

    recordJSON, err := json.Marshal(record)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(id, recordJSON)
}

// GrantAccess grants access to a health record for a specific organization
func (s *SmartContract) GrantAccess(ctx contractapi.TransactionContextInterface, id string, organizationID string) error {
    record, err := s.ReadHealthRecord(ctx, id)
    if err != nil {
        return err
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Verify that the client is from the provider organization or is the patient
    clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
    if err != nil {
        return fmt.Errorf("failed to get client MSPID: %v", err)
    }

    // In a real implementation, you would verify that the client is either the provider or the patient
    // For simplicity, we're just checking if the client has access to the record
    hasAccess := false
    for _, org := range record.AccessPermissions {
        if org == clientMSPID {
            hasAccess = true
            break
        }
    }

    if !hasAccess {
        return fmt.Errorf("client from %s is not authorized to grant access to this record", clientMSPID)
    }

    // Check if the organization already has access
    for _, org := range record.AccessPermissions {
        if org == organizationID {
            return fmt.Errorf("organization %s already has access to this record", organizationID)
        }
    }

    // Grant access
    record.AccessPermissions = append(record.AccessPermissions, organizationID)

    // Add event to history
    record.History = append(record.History, Event{
        Timestamp: time.Now(),
        Action:    "ACCESS_GRANTED",
        Actor:     clientID,
        Details:   fmt.Sprintf("Access granted to organization %s", organizationID),
    })

    recordJSON, err := json.Marshal(record)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(id, recordJSON)
}

// RevokeAccess revokes access to a health record for a specific organization
func (s *SmartContract) RevokeAccess(ctx contractapi.TransactionContextInterface, id string, organizationID string) error {
    record, err := s.ReadHealthRecord(ctx, id)
    if err != nil {
        return err
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Verify that the client is from the provider organization or is the patient
    clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
    if err != nil {
        return fmt.Errorf("failed to get client MSPID: %v", err)
    }

    // In a real implementation, you would verify that the client is either the provider or the patient
    // For simplicity, we're just checking if the client has access to the record
    hasAccess := false
    for _, org := range record.AccessPermissions {
        if org == clientMSPID {
            hasAccess = true
            break
        }
    }

    if !hasAccess {
        return fmt.Errorf("client from %s is not authorized to revoke access to this record", clientMSPID)
    }

    // Cannot revoke access from the provider
    if organizationID == record.Provider {
        return fmt.Errorf("cannot revoke access from the provider organization")
    }

    // Revoke access
    var newPermissions []string
    for _, org := range record.AccessPermissions {
        if org != organizationID {
            newPermissions = append(newPermissions, org)
        }
    }

    // Check if the organization had access
    if len(newPermissions) == len(record.AccessPermissions) {
        return fmt.Errorf("organization %s does not have access to this record", organizationID)
    }

    record.AccessPermissions = newPermissions

    // Add event to history
    record.History = append(record.History, Event{
        Timestamp: time.Now(),
        Action:    "ACCESS_REVOKED",
        Actor:     clientID,
        Details:   fmt.Sprintf("Access revoked from organization %s", organizationID),
    })

    recordJSON, err := json.Marshal(record)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(id, recordJSON)
}

// CreateConsent creates a new consent record
func (s *SmartContract) CreateConsent(ctx contractapi.TransactionContextInterface, id string, patientID string, organizationID string, purpose string, expiryDate string) error {
    exists, err := s.ConsentExists(ctx, id)
    if err != nil {
        return err
    }
    if exists {
        return fmt.Errorf("the consent record %s already exists", id)
    }

    // Parse expiry date
    expDate, err := time.Parse(time.RFC3339, expiryDate)
    if err != nil {
        return fmt.Errorf("invalid expiry date format: %v", err)
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // In a real implementation, you would verify that the client is the patient or an authorized representative
    // For simplicity, we're skipping this check

    // Create the consent record
    consent := ConsentRecord{
        ID:             id,
        PatientID:      patientID,
        OrganizationID: organizationID,
        Purpose:        purpose,
        GrantedDate:    time.Now(),
        ExpiryDate:     expDate,
        Status:         "ACTIVE",
    }

    consentJSON, err := json.Marshal(consent)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(fmt.Sprintf("CONSENT_%s", id), consentJSON)
}

// RevokeConsent revokes a consent record
func (s *SmartContract) RevokeConsent(ctx contractapi.TransactionContextInterface, id string) error {
    consentKey := fmt.Sprintf("CONSENT_%s", id)
    consentJSON, err := ctx.GetStub().GetState(consentKey)
    if err != nil {
        return fmt.Errorf("failed to read from world state: %v", err)
    }
    if consentJSON == nil {
        return fmt.Errorf("the consent record %s does not exist", id)
    }

    var consent ConsentRecord
    err = json.Unmarshal(consentJSON, &consent)
    if err != nil {
        return err
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // In a real implementation, you would verify that the client is the patient or an authorized representative
    // For simplicity, we're skipping this check

    // Revoke the consent
    consent.Status = "REVOKED"

    consentJSON, err = json.Marshal(consent)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(consentKey, consentJSON)
}

// QueryHealthRecordsByPatient returns all health records for a specific patient
func (s *SmartContract) QueryHealthRecordsByPatient(ctx contractapi.TransactionContextInterface, patientID string) ([]*HealthDataRecord, error) {
    queryString := fmt.Sprintf(`{"selector":{"patientId":"%s"}}`, patientID)

    return s.getQueryResultForQueryString(ctx, queryString)
}

// QueryHealthRecordsByProvider returns all health records from a specific provider
func (s *SmartContract) QueryHealthRecordsByProvider(ctx contractapi.TransactionContextInterface, provider string) ([]*HealthDataRecord, error) {
    queryString := fmt.Sprintf(`{"selector":{"provider":"%s"}}`, provider)

    return s.getQueryResultForQueryString(ctx, queryString)
}

// HealthRecordExists returns true when health record with given ID exists in world state
func (s *SmartContract) HealthRecordExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) {
    recordJSON, err := ctx.GetStub().GetState(id)
    if err != nil {
        return false, fmt.Errorf("failed to read from world state: %v", err)
    }

    return recordJSON != nil, nil
}

// ConsentExists returns true when consent record with given ID exists in world state
func (s *SmartContract) ConsentExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) {
    consentJSON, err := ctx.GetStub().GetState(fmt.Sprintf("CONSENT_%s", id))
    if err != nil {
        return false, fmt.Errorf("failed to read from world state: %v", err)
    }

    return consentJSON != nil, nil
}

// Helper function to check if valid consent exists
func (s *SmartContract) checkConsent(ctx contractapi.TransactionContextInterface, patientID string, organizationID string) (bool, error) {
    queryString := fmt.Sprintf(`{"selector":{"patientId":"%s","organizationId":"%s","status":"ACTIVE"}}`, patientID, organizationID)

    resultsIterator, err := ctx.GetStub().GetQueryResult(queryString)
    if err != nil {
        return false, err
    }
    defer resultsIterator.Close()

    // Check if there's at least one valid consent
    if resultsIterator.HasNext() {
        queryResponse, err := resultsIterator.Next()
        if err != nil {
            return false, err
        }

        var consent ConsentRecord
        err = json.Unmarshal(queryResponse.Value, &consent)
        if err != nil {
            return false, err
        }

        // Check if the consent is expired
        if consent.ExpiryDate.Before(time.Now()) {
            return false, nil
        }

        return true, nil
    }

    return false, nil
}

// Helper function to get client identity
func (s *SmartContract) getClientIdentity(ctx contractapi.TransactionContextInterface) (string, error) {
    clientID, err := ctx.GetClientIdentity().GetID()
    if err != nil {
        return "", fmt.Errorf("failed to get client identity: %v", err)
    }

    return clientID, nil
}

// Helper function for rich queries
func (s *SmartContract) getQueryResultForQueryString(ctx contractapi.TransactionContextInterface, queryString string) ([]*HealthDataRecord, error) {
    resultsIterator, err := ctx.GetStub().GetQueryResult(queryString)
    if err != nil {
        return nil, err
    }
    defer resultsIterator.Close()

    var records []*HealthDataRecord
    for resultsIterator.HasNext() {
        queryResponse, err := resultsIterator.Next()
        if err != nil {
            return nil, err
        }

        var record HealthDataRecord
        err = json.Unmarshal(queryResponse.Value, &record)
        if err != nil {
            return nil, err
        }
        records = append(records, &record)
    }

    return records, nil
}

func main() {
    chaincode, err := contractapi.NewChaincode(&SmartContract{})
    if err != nil {
        fmt.Printf("Error creating health data chaincode: %v\n", err)
        return
    }

    if err := chaincode.Start(); err != nil {
        fmt.Printf("Error starting health data chaincode: %v\n", err)
    }
}

Government and Public Sector

Hyperledger Fabric is being used by governments to improve transparency, efficiency, and trust in public services.

Land Registry

Several countries are implementing land registry systems on Hyperledger Fabric to improve property rights management and reduce fraud.

Key Features: - Immutable record of land ownership and transfers - Transparent property transactions - Reduced fraud and disputes - Streamlined property registration process

Technical Implementation: - Multi-organization network with government agencies, notaries, and financial institutions - Smart contracts for property registration and transfer - Integration with existing land registry systems - Public access for property verification

Sample Chaincode for Land Registry:

package main

import (
    "encoding/json"
    "fmt"
    "time"

    "github.com/hyperledger/fabric-contract-api-go/contractapi"
)

// Property represents a land property
type Property struct {
    ID              string    `json:"id"`
    Location        Location  `json:"location"`
    Area            float64   `json:"area"`
    OwnerID         string    `json:"ownerId"`
    RegistrationDate time.Time `json:"registrationDate"`
    Value           float64   `json:"value"`
    Status          string    `json:"status"`
    History         []Event   `json:"history"`
}

// Location represents a property location
type Location struct {
    Address     string    `json:"address"`
    City        string    `json:"city"`
    State       string    `json:"state"`
    Country     string    `json:"country"`
    PostalCode  string    `json:"postalCode"`
    Coordinates string    `json:"coordinates"`
}

// Event represents a property event
type Event struct {
    Timestamp time.Time `json:"timestamp"`
    Action    string    `json:"action"`
    Actor     string    `json:"actor"`
    Details   string    `json:"details"`
}

// TransferRequest represents a property transfer request
type TransferRequest struct {
    ID              string    `json:"id"`
    PropertyID      string    `json:"propertyId"`
    CurrentOwnerID  string    `json:"currentOwnerId"`
    NewOwnerID      string    `json:"newOwnerId"`
    RequestDate     time.Time `json:"requestDate"`
    TransferAmount  float64   `json:"transferAmount"`
    Status          string    `json:"status"`
    ApprovalStatus  map[string]string `json:"approvalStatus"`
}

// SmartContract provides functions for managing land registry
type SmartContract struct {
    contractapi.Contract
}

// RegisterProperty registers a new property
func (s *SmartContract) RegisterProperty(ctx contractapi.TransactionContextInterface, id string, address string, city string, state string, country string, postalCode string, coordinates string, area float64, ownerID string, value float64) error {
    exists, err := s.PropertyExists(ctx, id)
    if err != nil {
        return err
    }
    if exists {
        return fmt.Errorf("the property %s already exists", id)
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Verify that the client is from the registry authority
    clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
    if err != nil {
        return fmt.Errorf("failed to get client MSPID: %v", err)
    }

    if clientMSPID != "RegistryAuthorityMSP" {
        return fmt.Errorf("client from %s is not authorized to register properties", clientMSPID)
    }

    // Create the property
    property := Property{
        ID: id,
        Location: Location{
            Address:    address,
            City:       city,
            State:      state,
            Country:    country,
            PostalCode: postalCode,
            Coordinates: coordinates,
        },
        Area:            area,
        OwnerID:         ownerID,
        RegistrationDate: time.Now(),
        Value:           value,
        Status:          "REGISTERED",
        History: []Event{
            {
                Timestamp: time.Now(),
                Action:    "REGISTERED",
                Actor:     clientID,
                Details:   fmt.Sprintf("Property %s was registered", id),
            },
        },
    }

    propertyJSON, err := json.Marshal(property)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(id, propertyJSON)
}

// ReadProperty returns the property stored in the world state with given id
func (s *SmartContract) ReadProperty(ctx contractapi.TransactionContextInterface, id string) (*Property, error) {
    propertyJSON, err := ctx.GetStub().GetState(id)
    if err != nil {
        return nil, fmt.Errorf("failed to read from world state: %v", err)
    }
    if propertyJSON == nil {
        return nil, fmt.Errorf("the property %s does not exist", id)
    }

    var property Property
    err = json.Unmarshal(propertyJSON, &property)
    if err != nil {
        return nil, err
    }

    return &property, nil
}

// UpdatePropertyValue updates the value of a property
func (s *SmartContract) UpdatePropertyValue(ctx contractapi.TransactionContextInterface, id string, newValue float64) error {
    property, err := s.ReadProperty(ctx, id)
    if err != nil {
        return err
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Verify that the client is from the registry authority
    clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
    if err != nil {
        return fmt.Errorf("failed to get client MSPID: %v", err)
    }

    if clientMSPID != "RegistryAuthorityMSP" {
        return fmt.Errorf("client from %s is not authorized to update property values", clientMSPID)
    }

    // Update the property value
    property.Value = newValue

    // Add event to history
    property.History = append(property.History, Event{
        Timestamp: time.Now(),
        Action:    "VALUE_UPDATED",
        Actor:     clientID,
        Details:   fmt.Sprintf("Property value updated to %.2f", newValue),
    })

    propertyJSON, err := json.Marshal(property)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(id, propertyJSON)
}

// CreateTransferRequest creates a new property transfer request
func (s *SmartContract) CreateTransferRequest(ctx contractapi.TransactionContextInterface, id string, propertyID string, currentOwnerID string, newOwnerID string, transferAmount float64) error {
    exists, err := s.TransferRequestExists(ctx, id)
    if err != nil {
        return err
    }
    if exists {
        return fmt.Errorf("the transfer request %s already exists", id)
    }

    // Check if property exists
    property, err := s.ReadProperty(ctx, propertyID)
    if err != nil {
        return err
    }

    // Verify that the current owner is correct
    if property.OwnerID != currentOwnerID {
        return fmt.Errorf("the current owner ID does not match the property's owner")
    }

    // Verify that the property is not already in a transfer process
    if property.Status == "TRANSFER_PENDING" {
        return fmt.Errorf("the property is already in a transfer process")
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Create the transfer request
    transferRequest := TransferRequest{
        ID:              id,
        PropertyID:      propertyID,
        CurrentOwnerID:  currentOwnerID,
        NewOwnerID:      newOwnerID,
        RequestDate:     time.Now(),
        TransferAmount:  transferAmount,
        Status:          "PENDING",
        ApprovalStatus:  map[string]string{
            "RegistryAuthorityMSP": "PENDING",
            "NotaryMSP": "PENDING",
            "BankMSP": "PENDING",
        },
    }

    transferRequestJSON, err := json.Marshal(transferRequest)
    if err != nil {
        return err
    }

    // Update property status
    property.Status = "TRANSFER_PENDING"

    // Add event to property history
    property.History = append(property.History, Event{
        Timestamp: time.Now(),
        Action:    "TRANSFER_REQUESTED",
        Actor:     clientID,
        Details:   fmt.Sprintf("Transfer request %s created", id),
    })

    propertyJSON, err := json.Marshal(property)
    if err != nil {
        return err
    }

    // Update the world state
    err = ctx.GetStub().PutState(fmt.Sprintf("TRANSFER_%s", id), transferRequestJSON)
    if err != nil {
        return fmt.Errorf("failed to put transfer request in world state: %v", err)
    }

    return ctx.GetStub().PutState(propertyID, propertyJSON)
}

// ApproveTransferRequest approves a property transfer request
func (s *SmartContract) ApproveTransferRequest(ctx contractapi.TransactionContextInterface, id string) error {
    // Get the transfer request
    transferRequestJSON, err := ctx.GetStub().GetState(fmt.Sprintf("TRANSFER_%s", id))
    if err != nil {
        return fmt.Errorf("failed to read from world state: %v", err)
    }
    if transferRequestJSON == nil {
        return fmt.Errorf("the transfer request %s does not exist", id)
    }

    var transferRequest TransferRequest
    err = json.Unmarshal(transferRequestJSON, &transferRequest)
    if err != nil {
        return err
    }

    // Check if the transfer request is still pending
    if transferRequest.Status != "PENDING" {
        return fmt.Errorf("the transfer request is not in PENDING status")
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Get client MSPID
    clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
    if err != nil {
        return fmt.Errorf("failed to get client MSPID: %v", err)
    }

    // Check if the client's organization is involved in the approval process
    _, exists := transferRequest.ApprovalStatus[clientMSPID]
    if !exists {
        return fmt.Errorf("client from %s is not involved in the approval process", clientMSPID)
    }

    // Update the approval status
    transferRequest.ApprovalStatus[clientMSPID] = "APPROVED"

    // Check if all approvals are complete
    allApproved := true
    for _, status := range transferRequest.ApprovalStatus {
        if status != "APPROVED" {
            allApproved = false
            break
        }
    }

    // If all approvals are complete, finalize the transfer
    if allApproved {
        transferRequest.Status = "APPROVED"

        // Get the property
        property, err := s.ReadProperty(ctx, transferRequest.PropertyID)
        if err != nil {
            return err
        }

        // Update the property
        property.OwnerID = transferRequest.NewOwnerID
        property.Status = "REGISTERED"
        property.Value = transferRequest.TransferAmount

        // Add event to property history
        property.History = append(property.History, Event{
            Timestamp: time.Now(),
            Action:    "TRANSFERRED",
            Actor:     clientID,
            Details:   fmt.Sprintf("Property transferred to %s", transferRequest.NewOwnerID),
        })

        propertyJSON, err := json.Marshal(property)
        if err != nil {
            return err
        }

        err = ctx.GetStub().PutState(transferRequest.PropertyID, propertyJSON)
        if err != nil {
            return fmt.Errorf("failed to update property in world state: %v", err)
        }
    }

    transferRequestJSON, err = json.Marshal(transferRequest)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(fmt.Sprintf("TRANSFER_%s", id), transferRequestJSON)
}

// RejectTransferRequest rejects a property transfer request
func (s *SmartContract) RejectTransferRequest(ctx contractapi.TransactionContextInterface, id string, reason string) error {
    // Get the transfer request
    transferRequestJSON, err := ctx.GetStub().GetState(fmt.Sprintf("TRANSFER_%s", id))
    if err != nil {
        return fmt.Errorf("failed to read from world state: %v", err)
    }
    if transferRequestJSON == nil {
        return fmt.Errorf("the transfer request %s does not exist", id)
    }

    var transferRequest TransferRequest
    err = json.Unmarshal(transferRequestJSON, &transferRequest)
    if err != nil {
        return err
    }

    // Check if the transfer request is still pending
    if transferRequest.Status != "PENDING" {
        return fmt.Errorf("the transfer request is not in PENDING status")
    }

    // Get client identity
    clientID, err := s.getClientIdentity(ctx)
    if err != nil {
        return err
    }

    // Get client MSPID
    clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
    if err != nil {
        return fmt.Errorf("failed to get client MSPID: %v", err)
    }

    // Check if the client's organization is involved in the approval process
    _, exists := transferRequest.ApprovalStatus[clientMSPID]
    if !exists {
        return fmt.Errorf("client from %s is not involved in the approval process", clientMSPID)
    }

    // Update the approval status
    transferRequest.ApprovalStatus[clientMSPID] = "REJECTED"
    transferRequest.Status = "REJECTED"

    // Get the property
    property, err := s.ReadProperty(ctx, transferRequest.PropertyID)
    if err != nil {
        return err
    }

    // Update the property status
    property.Status = "REGISTERED"

    // Add event to property history
    property.History = append(property.History, Event{
        Timestamp: time.Now(),
        Action:    "TRANSFER_REJECTED",
        Actor:     clientID,
        Details:   fmt.Sprintf("Transfer request rejected: %s", reason),
    })

    propertyJSON, err := json.Marshal(property)
    if err != nil {
        return err
    }

    err = ctx.GetStub().PutState(transferRequest.PropertyID, propertyJSON)
    if err != nil {
        return fmt.Errorf("failed to update property in world state: %v", err)
    }

    transferRequestJSON, err = json.Marshal(transferRequest)
    if err != nil {
        return err
    }

    return ctx.GetStub().PutState(fmt.Sprintf("TRANSFER_%s", id), transferRequestJSON)
}

// QueryPropertiesByOwner returns all properties owned by a specific owner
func (s *SmartContract) QueryPropertiesByOwner(ctx contractapi.TransactionContextInterface, ownerID string) ([]*Property, error) {
    queryString := fmt.Sprintf(`{"selector":{"ownerId":"%s"}}`, ownerID)

    return s.getQueryResultForQueryString(ctx, queryString)
}

// QueryPropertiesByLocation returns all properties in a specific location
func (s *SmartContract) QueryPropertiesByLocation(ctx contractapi.TransactionContextInterface, city string, state string) ([]*Property, error) {
    queryString := fmt.Sprintf(`{"selector":{"location.city":"%s","location.state":"%s"}}`, city, state)

    return s.getQueryResultForQueryString(ctx, queryString)
}

// PropertyExists returns true when property with given ID exists in world state
func (s *SmartContract) PropertyExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) {
    propertyJSON, err := ctx.GetStub().GetState(id)
    if err != nil {
        return false, fmt.Errorf("failed to read from world state: %v", err)
    }

    return propertyJSON != nil, nil
}

// TransferRequestExists returns true when transfer request with given ID exists in world state
func (s *SmartContract) TransferRequestExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) {
    transferRequestJSON, err := ctx.GetStub().GetState(fmt.Sprintf("TRANSFER_%s", id))
    if err != nil {
        return false, fmt.Errorf("failed to read from world state: %v", err)
    }

    return transferRequestJSON != nil, nil
}

// Helper function to get client identity
func (s *SmartContract) getClientIdentity(ctx contractapi.TransactionContextInterface) (string, error) {
    clientID, err := ctx.GetClientIdentity().GetID()
    if err != nil {
        return "", fmt.Errorf("failed to get client identity: %v", err)
    }

    return clientID, nil
}

// Helper function for rich queries
func (s *SmartContract) getQueryResultForQueryString(ctx contractapi.TransactionContextInterface, queryString string) ([]*Property, error) {
    resultsIterator, err := ctx.GetStub().GetQueryResult(queryString)
    if err != nil {
        return nil, err
    }
    defer resultsIterator.Close()

    var properties []*Property
    for resultsIterator.HasNext() {
        queryResponse, err := resultsIterator.Next()
        if err != nil {
            return nil, err
        }

        var property Property
        err = json.Unmarshal(queryResponse.Value, &property)
        if err != nil {
            return nil, err
        }
        properties = append(properties, &property)
    }

    return properties, nil
}

func main() {
    chaincode, err := contractapi.NewChaincode(&SmartContract{})
    if err != nil {
        fmt.Printf("Error creating land registry chaincode: %v\n", err)
        return
    }

    if err := chaincode.Start(); err != nil {
        fmt.Printf("Error starting land registry chaincode: %v\n", err)
    }
}

Lessons Learned from Real-World Implementations

Based on these case studies and other real-world implementations, several key lessons have emerged:

  1. Start Small and Scale:
  2. Begin with a minimum viable product (MVP) focused on core functionality
  3. Validate the solution with a small group of users before expanding
  4. Incrementally add features based on user feedback

  5. Focus on Business Value:

  6. Clearly define the business problem and how blockchain solves it
  7. Quantify the expected benefits (cost savings, time reduction, etc.)
  8. Ensure all stakeholders understand the value proposition

  9. Address Governance Early:

  10. Establish clear governance structures for network management
  11. Define roles, responsibilities, and decision-making processes
  12. Create policies for onboarding new participants and handling disputes

  13. Plan for Integration:

  14. Design for integration with existing systems from the start
  15. Use standard APIs and data formats
  16. Implement proper error handling and data validation

  17. Consider Privacy and Regulatory Compliance:

  18. Understand and address relevant regulations (GDPR, HIPAA, etc.)
  19. Use private data collections for sensitive information
  20. Implement proper access controls and audit trails

  21. Invest in User Experience:

  22. Develop intuitive user interfaces that hide blockchain complexity
  23. Provide clear documentation and training
  24. Gather and incorporate user feedback

  25. Plan for Maintenance and Upgrades:

  26. Establish processes for chaincode upgrades
  27. Implement monitoring and alerting
  28. Create backup and recovery procedures

By learning from these real-world implementations, organizations can increase their chances of success when deploying Hyperledger Fabric solutions in production environments.