Skip to content

Hyperledger Fabric chaincode for managing medical records with full audit trail, including patients and medical history.

Notifications You must be signed in to change notification settings

OsamaRab3/MedicalContract

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MedicalContract Chaincode (Node.js)

This repository contains a Hyperledger Fabric chaincode (smart contract) implemented in Node.js for managing patients and their medical records.

  • Entry point: index.js (exports the contract)
  • Contract implementation: lib/medicalContract.js

Overview

The MedicalContract provides basic CRUD-style transactions for:

  • Patient registration
  • Adding and updating medical records
  • Querying patients and medical records
  • Retrieving key history

Data is stored as simple JSON documents in the Fabric world state with docType used for rich queries:

  • Patients: { patientId, name, nationalId, dateOfBirth, docType: 'patient' }
  • Medical Records: { recordId, patientId, doctorId, diagnosis, treatment, timestamp, docType: 'medicalRecord' }

Rich queries (CouchDB) are used to list all patients or all medical records by docType.

File Structure

  • index.js – Exports the MedicalContract for Fabric chaincode runtime
  • lib/medicalContract.js – Contract logic
  • package.json – Dependencies and scripts

Contract API

Class: MedicalContract (extends fabric-contract-api.Contract)

Transactions:

  1. initLedger(ctx)

    • Current behavior: Only logs Ledger initialized to the chaincode logger; it does not write any data.
    • Notes:
      • This is safe to invoke multiple times (idempotent) as it does not mutate state.
      • Typical usage is to preload sample data to the ledger; see the "Enhancements" section below for guidance.
  2. CreatePatient(ctx, patientId, name, nationalId, dateOfBirth)

    • Creates a patient document with docType: 'patient'.
    • Fails if a patient with the same patientId already exists.
    • Returns the created patient JSON string.
  3. AddMedicalRecord(ctx, recordId, patientId, doctorId, diagnosis, treatment)

    • Requires an existing patient (patientId).
    • Creates a medical record with docType: 'medicalRecord' and a timestamp derived from the transaction timestamp (ctx.stub.getTxTimestamp()), serialized as ISO string.
    • Returns the created record JSON string.
  4. UpdateMedicalRecord(ctx, recordId, newDiagnosis, newTreatment)

    • Updates an existing medical record’s diagnosis, treatment, and timestamp.
    • Fails if the record does not exist.
    • Returns the updated record JSON string.
  5. GetPatientHistory(ctx, key)

    • Streams history for the specified key and returns an array of { txId, timestamp, isDelete, value }.
    • Known issue: The current implementation returns from inside the iteration loop, which will prematurely exit after the first iteration. Consider fixing by moving the return JSON.stringify(history) statement after the loop terminates.
  6. QueryAllPatients(ctx)

    • Rich query by docType: 'patient'. Requires CouchDB state database.
    • Returns an array of patient objects.
  7. QueryAllMedicalRecords(ctx)

    • Rich query by docType: 'medicalRecord'. Requires CouchDB state database.
    • Returns an array of medical record objects.

Review Notes (initLedger and lib)

  • initLedger

    • Currently no-op other than logging. This is acceptable for bootstrap but does not populate any sample data.
    • Safe to call repeatedly.
  • General observations in lib/medicalContract.js

    • Uses ctx.stub.getTxTimestamp() for timestamps, which is suitable for deterministic state changes across endorsers.
    • Rich queries rely on docType. For production performance, consider adding CouchDB indexes in META-INF/statedb/couchdb/indexes.
    • Minor: const crypto = require('crypto'); is imported but not used and can be removed.
    • Bug: GetPatientHistory returns within the while (true) loop and will likely only produce a partial result. Move the return outside the loop.

Prerequisites

  • Node.js LTS and npm
  • Hyperledger Fabric v2.x peer/orderer network with CouchDB for rich queries
  • The Fabric Node.js contract runtime (fabric-contract-api, fabric-shim) – already declared in package.json

Install Dependencies

npm install

Running as Chaincode-as-a-Service (external chaincode)

This project includes a start script that launches the chaincode server and connects to a peer.

Script (from package.json):

"start": "fabric-chaincode-node start --peer.address localhost:7051 chaincode-id-name \"medical-contract:1.0.0\""

Notes:

  • Ensure your peer is reachable at localhost:7051 or adjust the address accordingly.
  • The chaincode-id-name must match the name used during chaincode definition in the Fabric lifecycle (e.g., medical-contract:1.0.0).
  • Configure TLS flags and environment variables as required by your network.

Start the chaincode server:

npm start

Then, use Fabric lifecycle to approve/commit the chaincode definition and point it to the external service according to your network’s setup.

Example Invocations (peer CLI)

Assuming:

  • Channel: mychannel
  • Chaincode name: medical-contract
  • JSON args use the Fabric v2 syntax

Initialize (does not write data):

peer chaincode invoke -C mychannel -n medical-contract -c '{"Args":["initLedger"]}'

Create a patient:

peer chaincode invoke -C mychannel -n medical-contract -c '{"Args":["CreatePatient","p1","Alice Smith","NAT-12345","1990-01-01"]}'

Add a medical record:

peer chaincode invoke -C mychannel -n medical-contract -c '{"Args":["AddMedicalRecord","r1","p1","dr-001","Flu","Rest and hydration"]}'

Update a medical record:

peer chaincode invoke -C mychannel -n medical-contract -c '{"Args":["UpdateMedicalRecord","r1","Seasonal flu","Antivirals"]}'

Query all patients (CouchDB rich query):

peer chaincode query -C mychannel -n medical-contract -c '{"Args":["QueryAllPatients"]}'

Query all medical records (CouchDB rich query):

peer chaincode query -C mychannel -n medical-contract -c '{"Args":["QueryAllMedicalRecords"]}'

Get history for a patient key:

peer chaincode query -C mychannel -n medical-contract -c '{"Args":["GetPatientHistory","p1"]}'

Adjust for TLS, MSP, and environment variables as required by your deployment.

About

Hyperledger Fabric chaincode for managing medical records with full audit trail, including patients and medical history.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published