- Star Registry Service that allows users to claim ownership of their favorite star in the night sky
 - Implemented as a blockchain that is persisted using LevelDB and made externally available via a Web API (HAPI framework)
 - A mempool stores validated and signed requests using LokiJS
 
Node is really easy to install & now include NPM. You should be able to run the following command after the installation procedure below:
$ node --version
v11.5.0
$ npm --version
6.5.0
To setup the project for review do the following:
$ git clone https://github.com/stevenhankin/udacity-private-blockchain.git
$ cd udacity-private-blockchain
$ npm install
Key files are listed below:
├── app
│   ├── api
│   │   └── routes.js      <-- Controller for HTTP routing, initialises mempool/ledger
│   ├── blockchain
│   │   ├── Block.js       <-- Block model
│   │   ├── BlockChain.js  <-- BlockChain functionality
│   │   └── Ledger.js      <-- Wrapper for LevelDB file storage
│   ├── mempool
│   │   ├── MemPool.js     <-- Wrapper for LokiJS in-memory database
│   │   └── Request.js     <-- Request model
│   └── server.js          <-- MAIN entry point
├── config
│   └── default.json       <-- Project constants
└── testNode modules, documentation, etc are not included above
To start the Web API on localhost:8000, run the following:
$ npm start
When the Web API service is running, just run the following in a separate shell:
$ npm test
This is a comprehensive test suite using Mocha
| Resource | Description | Example | 
|---|---|---|
| Request Validation | /requestValidation | curl -X POST   http://localhost:8000/requestValidation -H 'Content-Type: application/json'    -H 'cache-control: no-cache'  -d '{    "address":"18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T"}' | 
| Validate a Signature | /message-signature/validate | curl -X POST http://localhost:8000/message-signature/validate -H 'Content-Type: application/json'   -H 'cache-control: no-cache'  -d '{"address":"18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T",   "signature":"H2mEWlo0AnE6XjUIkDpSV93XAawqib3kHa+uIPWGphklO+bF5hrMNdVqu0NTgVvolZ/WV6uJi8mwXB/7by8K0KQ="}' | 
| Post a claim for a star | /block | curl -X POST http://localhost:8000/block-H 'Content-Type: application/json'-H 'cache-control: no-cache' -d $'{"address":"18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T",  "star": {"dec": "68° 52\' 56.9","ra": "16h 29m 1.0s","story": "Found star using https://www.google.com/sky/"}}' | 
| Get star block by block hash | /stars/hash:[HASH] | curl -X GET http://localhost:8000/stars/hash:6f508d6ab09a044e7dd2795b76f0945fb48ae670d4ce547a46594f6d13931d1c -H 'Content-Type: application/json'   -H 'cache-control: no-cache' | 
| Get stars by wallet address | /stars/address:[ADDRESS] | curl -X GET http://localhost:8000/stars/address:18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T -H 'Content-Type: application/json'   -H 'cache-control: no-cache' | 
| Get star block by block height | /block/{height} | curl --location --request GET "http://localhost:8000/block/1" | 
| Get BlockChain info | /info | curl --location --request GET "http://localhost:8000/info" | 
| Validate BlockChain | /validateChain | curl --location --request GET "http://localhost:8000/validateChain" | 
Below are examples of inputs and formatted outputs from CLI
curl -X POST   http://localhost:8000/requestValidation \
        -H 'Content-Type: application/json' \
        -H 'cache-control: no-cache'  -d '{"address":"18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T"}'{
  "walletAddress": "18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T",
  "requestTimeStamp": "1546255945",
  "message": "18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T:1546255945:starRegistry",
  "validationWindow": 300
}curl -X POST \
  http://localhost:8000/message-signature/validate \
  -H 'Content-Type: application/json' \
  -H 'cache-control: no-cache' \
  -d '{"address":"18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T",   
       "signature":"H6CdLlHZBfDcUbl2iGzMFXPVfn4EEtHLagia4yQP1M6vDxuk7PSg71lr6Cb75DeF+HrSnooqjKAYFlHcfeOruSk="}'{
  "registerStar": true,
  "status": {
    "address": "18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T",
    "requestTimeStamp": "1546256313",
    "message": "18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T:1546256313:starRegistry",
    "validationWindow": 300,
    "messageSignature": true
  }
}curl -X POST \
  http://localhost:8000/block \
  -H 'Content-Type: application/json' \
  -H 'cache-control: no-cache' \
  -d $'{"address":"18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T", 
       "star": {
                "dec": "68° 52\' 56.9",
                "ra": "16h 29m 1.0s",
                "story": "Found star using https://www.google.com/sky/"
            }
}'{
  "hash": "78cd0333a2065660785244293241007ac5a029b881fbc873c00ac9d96bca7364",
  "height": 31,
  "body": {
    "address": "18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T",
    "star": {
      "dec": "68° 52' 56.9",
      "ra": "16h 29m 1.0s",
      "story": "466f756e642073746172207573696e672068747470733a2f2f7777772e676f6f676c652e636f6d2f736b792f"
    }
  },
  "time": "1546256476",
  "previousBlockHash": "ab499550ea6b727ae5148eda016d4f2b03605b40038943935d8044cd2256e328"
}curl -X GET http://localhost:8000/stars/hash:78cd0333a2065660785244293241007ac5a029b881fbc873c00ac9d96bca7364  \
     -H 'Content-Type: application/json'  \
     -H 'cache-control: no-cache' {
  "hash": "78cd0333a2065660785244293241007ac5a029b881fbc873c00ac9d96bca7364",
  "height": 31,
  "body": {
    "address": "18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T",
    "star": {
      "dec": "68° 52' 56.9",
      "ra": "16h 29m 1.0s",
      "story": "466f756e642073746172207573696e672068747470733a2f2f7777772e676f6f676c652e636f6d2f736b792f",
      "storyDecoded": "Found star using https://www.google.com/sky/"
    }
  },
  "time": "1546256476",
  "previousBlockHash": "ab499550ea6b727ae5148eda016d4f2b03605b40038943935d8044cd2256e328"
}curl -X GET http://localhost:8000/stars/address:18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T  \
     -H 'Content-Type: application/json' -H 'cache-control: no-cache' [
  {
    "hash": "78cd0333a2065660785244293241007ac5a029b881fbc873c00ac9d96bca7364",
    "height": 31,
    "body": {
      "address": "18ecEqCy8LfsK17b4v5ansJfXpiyhDzB3T",
      "star": {
        "dec": "68° 52' 56.9",
        "ra": "16h 29m 1.0s",
        "story": "466f756e642073746172207573696e672068747470733a2f2f7777772e676f6f676c652e636f6d2f736b792f",
        "storyDecoded": "Found star using https://www.google.com/sky/"
      }
    },
    "time": "1546256476",
    "previousBlockHash": "ab499550ea6b727ae5148eda016d4f2b03605b40038943935d8044cd2256e328"
  }
]curl -X GET http://localhost:8000/block/1 -H 'Content-Type: application/json'   -H 'cache-control: no-cache'{
  "hash": "dd3cb5c31adb75702ae97bd0b79e0cf92d4286d9dc0cfe5f41a40158bf1c0d65",
  "height": 1,
  "body": {
    "address": "1DHEcCVTpQisJVwoDtoSzyD86SwzmY4UzG",
    "star": {
      "dec": "68° 52' 56.9",
      "ra": "16h 29m 1.0s",
      "story": "466f756e642073746172207573696e672068747470733a2f2f7777772e676f6f676c652e636f6d2f736b792f",
      "storyDecoded": "Found star using https://www.google.com/sky/"
    }
  },
  "time": "1546255664",
  "previousBlockHash": "78c601d161387579963fd8462717c53b188ce95f8baffb612edc4df8b50768a5"
}Documentation can be generated via esdoc as follows:
$ npm run docs
The html output will be in the ./docs subfolder