Last weekend I attended NextStep Hacks, a hackathon sponsored by Ethereum. I was interested in blockchain for a long time, but this is my first time developing a blockchain project.
In two days, my teammate Akilesh and I learned the basics and built a simple healthcare Dapp, which ended up winning the 3rd place. Here I'll share how I built it and hopefully it will help you jump start with blockchain development ⏫
Inspiration
For decades, medical records are under the ownership of hospitals. It often it takes days to request a hospital to transfer a record, and sometimes impossible to transfer across countries.
When I arrived at US for college, I tried to transfer records of Covid vaccination from China, but rejected by local hospitals. I had to take two more dozes of Pfizer and suffering days of side effects like fever 😣
That's why we built MedChain - a blockchain-based electrical medical records (EMR) decentralized application (Dapp).
How it works
MedChain is powered by IPFS, where patients’ medical records are stored on the distributed file system, not owned by any centralized entity.
A patient or a doctor can access the patient's records by interacting with a smart contract on the Ethereum blockchain. Here is a graph showing how the Dapp works:
The client first connects with MetaMask, and uses smart contract to mint a patient or doctor block, registered by the wallet address.
The client can upload a record file to IPFS, which address is linked to a patient block in ETH chain. The client can get all record addressed stored in a patient block from smart contract, and get a record file by its address from IPFS.
Setup
We chose Truffle, a powerful development tool for Ethereum, and React since it's our most familiar frontend framework.
We used Truffle React Box as a boilerplate for this project. It already has React context set up to connect with MetaMask and interact with Truffle.
To get a local blockchain network running on my computer, I set up Ganache and imported test accounts to MetaMask.
Write smart contract
For this project, we only need one Solidity smart contract called EHR. First I defined structures for medical record, patient, and doctor.
Then functions to register user. A doctor can register itself and register patients.
Finally, functions to add and get records of a patient. Only a doctor can add records, but both doctor and patient can read records.
To deploy the contract, run truffle deploy
and EHR.sol
will be deployed as EHR.json
.
Connect React with smart contract
Skipping writing components, the important part of this React project is iteracting with the smart contract.
With ETH context provided in the boilterplate, it sets up Web3.js initialization for me. You can find the same logic as the following:
Since the constants above are stored in context, I can use them easily in a register button component.
The same thing applies to register patient with the patient account as input.
Upload & Download record from IPFS
Another important part is uploading records to IPFS and pushing address to the smart contract. I used ipfs-http-client to handle this easily in React.
First I set up IPFS client using my Infura project. Infura is an infrastructure tool to use IPFS API.
After a doctor drags a file in the dropzone, FileReader
reads it as a buffer and upload it to IPFS client.
Then I call addRecord
contract method with the patient address and the hash returned by IPFS client. Lastly, call getRecords
to refresh records.
Then a patient or doctor can download the record in one click.
Final product
You can check out our repo and our project on DevPost.
We hope our project help push revolutionizing the centralized ownership of medical records and let people own their health. Go blockchain 🚀
Top comments (22)
Great article! It's fascinating to see how Solidity and React can be used to build a simple healthcare Dapp. The combination of blockchain technology and web development frameworks opens up exciting possibilities for the healthcare industry. For more insights and information on creating EMR and EHR systems, I recommend checking out this article by Cleveroad. It provides valuable guidance on building robust and secure electronic medical record systems. Keep up the good work!
Hi Jeffrey Yu, This is very great Idea. I had the same project about this. And I had an error when doing npm start like this:
C:\Users\ADMIN\thesis_bc\client>npm start
i 「wds」: Project is running at 0.0.0.0:3000/
i 「wds」: webpack output is served from
i 「wds」: Content not from webpack is served from C:\Users\ADMIN\thesis_bc\client\public
i 「wds」: 404s will fallback to /
Starting the development server...
Compiled with warnings.
./src/contexts/EthContext/EthProvider.jsx
Module not found: Can't resolve '../../contracts/SimpleStorage.json' in 'C:\Users\ADMIN\thesis_bc\client\src\contexts\EthContext'
Search for the keywords to learn more about each warning.
To ignore, add // eslint-disable-next-line to the line before.
Can you give me any suggestion!
Hi Thang, sorry for the late reply. Make sure you compiled and deployed your truffle contract under
client\src\contracts
and the name is the same as the imported one inEthContext
.Hi Jeffrey Yu , I wonder, when the doctor uploads the record file, is there anything to show its immutability. As you know, the purpose of Blockchain is immutable, so when creating a transaction to upload a file, is there a hash or identifier for it. And where is it saved? Can I see them?
The immutability concept in blockchain is to retain an unalterable history of transactions. In the case of this project, the patient can see every edit history made to his or her record. This is implement-able.
Did you manage to resolve this problem? If so, what did you do? I'm having the same issues
Hi Sergizzzz. This is what I did and it was very great. You download file from Git, then from the root directory of that file install npm + truffle if you dont have. Then, cd to the truffle directory: ' truffle compile' - 'truffle migrate'. Make sure that you open your ganache or testnet. After that, cd to client folder: 'npm start'. I worked for me
Hello, is this project on public blockchain? How do you ensure sensitive data security, if data will be forever on chain? Are you encrypt that data?
Thanks in advance :)
Hi Reako, this is a hackathon project so I didn't publish it to the public network. Security measures like encryption and authorization is definitely necessary for that case.
same question
$ cd truffle
$ npm install
$ truffle compile
$ truffle deploy
$ cd ../client
$ npm install
npm ERR! code 128
npm ERR! An unknown git error occurred
npm ERR! command git --no-replace-objects ls-remote ssh://git@github.com/hugomrdias/concat-stream.git
npm ERR! git@github.com: Permission denied (publickey).
npm ERR! fatal: Could not read from remote repository.
npm ERR!
npm ERR! Please make sure you have the correct access rights
npm ERR! and the repository exists.
I'm getting this error, please help me out.
Hi Jeffrey
It was fascinating idea. Was trying to run the code. Took the code from the Git - github.com/JeffreytheCoder/med-chain
Ran all the commands :
$ cd truffle
$ npm install
$ truffle compile
$ truffle deploy
$ cd ../client
$ npm install
$ npm start
localhost:3000 - opened in my chrome and the first page i could see. But after that nothings happened can not even register doctor. Here is the log:
*index.js:1 TypeError: Cannot read properties of undefined (reading 'address')
at EthProvider.jsx:17:1
console. @ index.js:1
index.js:1 TypeError: Cannot read properties of undefined (reading 'address')
at EthProvider.jsx:17:1
console. @ index.js:1
index.js:1 TypeError: Cannot read properties of undefined (reading 'methods')
at registerDoctor (index.jsx:24:1)
at handleClick (index.jsx:45:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
at invokeGuardedCallback (react-dom.development.js:4277:1)
at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4291:1)
at executeDispatch (react-dom.development.js:9041:1)
at processDispatchQueueItemsInOrder (react-dom.development.js:9073:1)
at processDispatchQueue (react-dom.development.js:9086:1)
at dispatchEventsForPlugins (react-dom.development.js:9097:1)
at react-dom.development.js:9288:1
at batchedUpdates$1 (react-dom.development.js:26140:1)
at batchedUpdates (react-dom.development.js:3991:1)
at dispatchEventForPluginEventSystem (react-dom.development.js:9287:1)
at dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay (react-dom.development.js:6465:1)
at dispatchEvent (react-dom.development.js:6457:1)
at dispatchDiscreteEvent (react-dom.development.js:6430:1)
console. @ index.js:1
overrideMethod @ react_devtools_backend.js:2655
registerDoctor @ index.jsx:29
handleClick @ index.jsx:45
callCallback @ react-dom.development.js:4164
invokeGuardedCallbackDev @ react-dom.development.js:4213
invokeGuardedCallback @ react-dom.development.js:4277
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:4291
executeDispatch @ react-dom.development.js:9041
processDispatchQueueItemsInOrder @ react-dom.development.js:9073
processDispatchQueue @ react-dom.development.js:9086
dispatchEventsForPlugins @ react-dom.development.js:9097
(anonymous) @ react-dom.development.js:9288
batchedUpdates$1 @ react-dom.development.js:26140
batchedUpdates @ react-dom.development.js:3991
dispatchEventForPluginEventSystem @ react-dom.development.js:9287
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ react-dom.development.js:6465
dispatchEvent @ react-dom.development.js:6457
dispatchDiscreteEvent @ react-dom.development.js:6430
*
Hi Shamik,
The error is because it could not get
networkID
of your local Truffle network. Make sure your local Truffle network is configured and running correctly. Here's a help page.Hello Jefrrey, I am a Blockchain fan from Venezuela, a medical student, I want to do my thesis on Blockchain Technology and its use in medicine and I have always loved this use case, how can I contact you, so that you can guide me And if your dapp is still in development!
Hi Moi, you can connect with me on LinkedIn: linkedin.com/in/jeffrey-zepeng-yu/. I would love to help!
$ cd truffle
$ npm install
$ truffle compile
$ truffle deploy
$ cd ../client
$ npm install
in this step I'm getting this
npm ERR! code 128
npm ERR! An unknown git error occurred
npm ERR! command git --no-replace-objects ls-remote ssh://git@github.com/hugomrdias/concat-stream.git
npm ERR! git@github.com: Permission denied (publickey).
npm ERR! fatal: Could not read from remote repository.
npm ERR!
npm ERR! Please make sure you have the correct access rights
npm ERR! and the repository exists.
I'm getting this error, please help me out.
Hi Shashank! Sorry for the late reply - I just saw your comment as another person with the same issue reached out to me.
The error is caused by a decrepated IPFS dependency and I just fixed it. If you pull the latest code it should be running ok.
Can we use Ubuntu 20.04 to install the development environment?
I installed everything like: Node.js v18.17.1, NPM v10.2.5, Truffle v5.11.5, Ganache v7.9.1, Solidity v0.5.16 (solc-js), Web3.js v1.10.0. Then I got this error:
med-chain-master/client$ npm install
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: @material-ui/core@4.12.4
npm ERR! Found: react@18.2.0
npm ERR! node_modules/react
npm ERR! react@"^18.1.0" from the root project
npm ERR! peer react@">=16.8.0" from @emotion/react@11.10.0
npm ERR! node_modules/@emotion/react
npm ERR! @emotion/react@"^11.10.0" from the root project
npm ERR! peer @emotion/react@"^11.0.0-rc.0" from @emotion/styled@11.10.0
npm ERR! node_modules/@emotion/styled
npm ERR! @emotion/styled@"^11.10.0" from the root project
npm ERR! 3 more (@mui/material, @mui/styled-engine, @mui/system)
npm ERR! 3 more (@mui/material, @mui/styled-engine, @mui/system)
npm ERR! 17 more (@emotion/styled, @mui/base, @mui/icons-material, ...)
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^16.8.0 || ^17.0.0" from @material-ui/core@4.12.4
npm ERR! node_modules/@material-ui/core
npm ERR! @material-ui/core@"^4.12.4" from the root project
npm ERR! peer @material-ui/core@"^4.0.0" from @material-ui/icons@4.11.3
npm ERR! node_modules/@material-ui/icons
npm ERR! @material-ui/icons@"^4.11.3" from the root project
npm ERR! 1 more (material-ui-dropzone)
npm ERR! 1 more (material-ui-dropzone)
npm ERR!
npm ERR! Conflicting peer dependency: react@17.0.2
npm ERR! node_modules/react
npm ERR! peer react@"^16.8.0 || ^17.0.0" from @material-ui/core@4.12.4
npm ERR! node_modules/@material-ui/core
npm ERR! @material-ui/core@"^4.12.4" from the root project
npm ERR! peer @material-ui/core@"^4.0.0" from @material-ui/icons@4.11.3
npm ERR! node_modules/@material-ui/icons
npm ERR! @material-ui/icons@"^4.11.3" from the root project
npm ERR! 1 more (material-ui-dropzone)
npm ERR! 1 more (material-ui-dropzone)
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
I tried all versions of Node and NPM and your damn project does not work. It is a waste of time.
You can run
npm install --force --legacy-peer-deps
as it's suggested in your error output. And please don't use bad language here.How did you leanr the basics! I have 2 days to work on a similar project, but mine is not patient _centered!
Some comments may only be visible to logged-in visitors. Sign in to view all comments.