The education industry has a big problem; in addition to the student debt crisis and other issues, post-student life is often a complete mess. One of these key areas is the credentialing process. Employers and students are often left hanging while employment verifications or the general verification process takes days (or even weeks) to finish. This leaves employers at risk of being understaffed, schools in danger of being short-staffed in their registrars' offices, and students in a position of losing out on great jobs. This is exactly the part where Stampd comes in.
Stampd is a blockchain-based project that allows educational institutions to permanently issue fully verified credentials that are stamped to the Ethereum blockchain. Using blockchain technology, educational institutions can have a fast and cost-effective way to take care of their students; within minutes, a school can issue a credential and email it out, while employers can have peace of mind in knowing that there's no secret way the credential could have been modified or tampered with. This enables fast hires, low budgetary costs, and happy employees.
Easy. Verified. Blockchain. Credentials with Stampd.
Aljoe Bacus | Brannan Conrad | Byron Holmes | Megan Jeffcoat | CJ Tantay | Nathan Thomas |
---|---|---|---|---|---|
|
|
|
|
|
- Introduction
- Contributors
- Getting Started
- Technology Stack
- API Examples
- Data Models
- Query and Mutation List
- Testing
- Project Management
- Contributing and Getting Involved
- Additional Documentation
- License
- Acknowledgements
This repository contains a yarn.lock file. Please do not remove this file from your local code, as the integrity of the application cannot be gauranteed (especially with packages such as Web3) if versions that may be incompatible with each other are used by installing the newest version of each dependency.
To get the server running locally, clone this repo and use the following commands/steps:
- Install
Node Version Manager
(ornvm
) by following the installation instructions here (due to dependency reasons, this project requires the use ofNode.js
version 10, andnvm
allows us to do this) - Use the yarn command in the root directory to install all required dependencies
- Use the nvm use 10 command to switch the
Node.js
version used to10
- Use the yarn server command in the root directory to start the local server
- Use the yarn test to start server using testing environment
In order for the app to function correctly, you must set up the correct environment variables. Please create a .env
file that includes the following:
* PORT = Port to run server on
* TESTING_DATABASE_URL = Url for testing database
* DATABASE_URL = Url for database
* NODE_SERVER_SENTRY = Sentry URI for continuous integration
* PK = Secret used for hashing JWTs
* REACT_APP_AUTH_TOKEN = Another secret used for hashing other JWTs
* CONTRACT_ADDRESS = Address of contract deployed to Ethereum blockchain
* INFURA = URL of Infura API
* PRIVATE_KEY = Private key for Infura
* ACCOUNT_1 = Owner address for Ethereum contract
The following is a short list of the major dependencies used (with the reasons we used them) followed by complete and exhaustive ones with all production and development packages incorporated in the server build.
- Javascript in the language of choice for the back-end
- Express allows for easy API creation
- Middleware patterns are easy and fluid in Express
- Built on top of Express
- One endpoint allows for fast development speed
- Schema is built into GraphQL Playground
- Works well with Heroku
- Web3 allows for a direct connection to the Ethereum Virtual Machine, or EVM
- Builds out suite of tools for connecting, posting, and retrieving data through the use of wallets
- @sentry/node
- cors
- dotenv
- ethereumjs-tx
- express
- express-graphql
- graphql
- graphql-playground-middleware-express
- helmet
- jsonwebtoken
- jwt-decode
- knex
- pg
- web3
- cross-env
- eslint
- eslint-config-airbnb-base
- eslint-config-prettier
- eslint-plugin-import
- eslint-plugin-prettier
- jest
- nodemon
- prettier
- supertest
The server is deployed at https://stampd-backend.herokuapp.com/.
The server IDE GraphQL Playground is deployed at https://stampd-backend.herokuapp.com/playground.
Here are some examples of a GraphQL query and mutation on this server along with corresponding JSON that is returned:
query {
getSchoolDetailsBySchoolId(id: 1) {
name
street1
street2
city
state
zip
type
phone
url
user {
email
}
}
}
{
"data": {
"getSchoolDetailsBySchoolId": {
"name": "School of the Midweast",
"street1": "Midway St.",
"street2": null,
"city": "Midway City",
"state": "MA",
"zip": "5050",
"type": "University",
"phone": "555-5555",
"url": "https://www.midweast.edu/",
"user": {
"email": "schoolzrus@rocketmail.com"
}
}
}
}
mutation {
addNewCredential(
criteria: "Asserts student has completed all requirements for certification in welding at Elgin Community College"
description: "Basic concepts of oxy-acetylene welding and electric welding for beginners."
expirationDate: "none"
imageUrl: "www.fakeurl.com"
issuedOn: "7/7/1917"
credName: "Certification in Welding"
ownerName: "Gary Oldman"
schoolId: "1"
studentEmail: "fakestudent@gmail.com"
type: "Certificate"
) {
id
credHash
txHash
}
}
{
"data": {
"addNewCredential": {
"id": "4",
"credHash": "0x8ae1d6e7efb7e492997844b76aa80b009a3d67f153ec09f119cfdb876d73d59d",
"txHash": "0x36f54937d5c1dce9fa949f4fa8fee048e6e20a0fa9949b98e847262d649a7f6d"
}
}
}
{
id: ID
type: String!
users: [User]
}
{
id: ID
username: String
email: String!
profilePicture: String
roleId: ID
sub: String!
token: String
tokenExpiration: Int
role: Role
schoolDetails: SchoolDetails
}
{
id: ID
name: String!
taxId: String!
street1: String
street2: String
city: String
state: String
zip: String
type: String
phone: String!
url: String!
userId: ID!
user: User
credentials: [Credential]
}
{
id: ID
credName: String!
description: String!
credHash: String
txHash: String
type: String!
ownerName: String!
studentEmail: String!
imageUrl: String!
criteria: String!
valid: Boolean
issuedOn: String!
expirationDate: String
schoolId: ID!
schoolsUserInfo: User
}
getAllUsers
-> gets all usersgetUserById(id: ID)
-> Gets a user by userIdgetAllSchoolDetails
-> Gets all school details (for testing only)getSchoolDetailsBySchoolId(id: ID)
-> Gets school details by schoolIdgetAllCredentials
-> Gets all credentialsgetCredentialById(id: ID)
-> Gets credential by credential IDgetCredentialsBySchoolId(id: ID)
-> Get all of a schools credentialsverifyCredential
-> Verifies a credential on the blockchain
addUser( authToken: String! roleId: ID )
-> Adds a new userupdateUser( id: ID! username: String email: String roleId: ID )
-> Updates a users informationdeleteUser(id: ID!)
-> Deletes a user by idaddSchoolDetail( name: String! taxId: String! street1: String street2: String city: String state: String zip: String type: String phone: String! url: String! userId: ID! )
-> Adds details for a schoolupdateSchoolDetail( id: ID! name: String taxId: String street1: String street2: String city: String state: String zip: String type: String phone: String url: String userId: ID )
-> Updates a schools detailsaddNewCredential( credName: String! description: String! txHash: String credHash: String type: String! ownerName: String! studentEmail: String! imageUrl: String! criteria: String! valid: Boolean issuedOn: String! expirationDate: String schoolId: ID! )
-> Adds a new credential to the database and blockchainupdateCredential( id: ID! credName: String description: String credHash: String txHash: String type: String ownerName: String studentEmail: String imageUrl: String criteria: String valid: Boolean issuedOn: String expirationDate: String schoolId: ID )
-> Updates a credential and reissues it on the blockchainremoveCredential(id: ID!): Credential invalidateCredential( id: ID! credName: String description: String credHash: String txHash: String type: String ownerName: String studentEmail: String imageUrl: String criteria: String valid: Boolean issuedOn: String expirationDate: String schoolId: ID )
-> Deletes a credentialvalidateCredential( id: ID! credName: String description: String credHash: String txHash: String type: String ownerName: String studentEmail: String imageUrl: String criteria: String valid: Boolean issuedOn: String expirationDate: String schoolId: ID )
Updates a credential to valid and reissues it on the blockchain
Testing is performed using the following dependency:
The following documents and links contain all the project management documents for Stampd. Included are a Trello board, the project vision document (which contains links to the UX wireframes and layouts), and the Google Drive with our user interviews:
If you spot a bug or would like to request a feature, we welcome and are grateful for any contributions from the community. Please review the process for contributing to this project by reading the contribution guidelines.
Also, please note we have a code of conduct. Please follow it in all your interactions with the project.
If you are having an issue with the existing project code, please submit a bug report under the following guidelines:
- Check first to see if your issue has already been reported.
- Check to see if the issue has recently been fixed by attempting to reproduce the issue using the latest master branch in the repository.
- Create a live example of the problem.
- Submit a detailed bug report including your environment & browser, steps to reproduce the issue, actual and expected outcomes, where you believe the issue is originating from, and any potential solutions you have considered.
We would love to hear from you about new features which would improve this app and further the aims of our project. Please provide as much detail and information as possible to show us why you think your new feature should be implemented.
- Ensure any install or build dependencies are removed before the end of the layer when doing a build.
- Update the README.md with details of changes to the interface, including new plist variables, exposed ports, useful file locations and container parameters.
- Ensure that your code conforms to our existing code conventions and test coverage.
- Include the relevant issue number, if applicable.
- You may merge the Pull Request in once you have the sign-off of two other developers, or if you do not have permission to do that, you may request the second reviewer to merge it for you.
See Front-end Documentation for details on the front-end client of our project.
- Lambda School - Thank you for educating us, equipping us with our current skillset, and pushing us towards success.
- Josh Knell - The Big Boss. The Big Cheese. Thanks for teaching us the basics and for keeping it real. Banjo on.
- Dustin Myers - The Legend himself. Dustin is the reason we can even write a single line of code in React. Thanks for your leadership, Dustin.
- Luis Hernandez - Luis, thanks for teaching us about the Bros and Homies. Your leadership in Lambda School back-end week lets us build servers and move mountains.
- John Mitchell - You opened up the statically-typed world of Java to us. Thank you for being a steady hand at the wheel when we needed it.
- Dan Levy - Thanks for all of your advice, Dan. You consistently come through with gold when we need it. Your advice is invaluable, and you care about students.
- Coffee - We'd like to thank coffee for the productivity of this Labs project. Seriously. Thanks.