Sign inSign up

hyperledgerlabs/supplychain_quorum

By hyperledgerlabs

Updated almost 5 years ago

Image
0

3.0K

hyperledgerlabs/supplychain_quorum repository overview

Supplychain Quorum Api microservice

This project contains an Express Node.js application which does request transformation for API requests from the front end react application for supplychain to the appropriate format for a smartcontract deployed on a private Quorum network.

Requirements

  1. If you need to install Node.js run the command

     brew install node 
    

    For Ubuntu OS:

     sudo apt-get update
     sudo apt-get install nodejs
    

    You will need to install npm, which is Node.js package manager.

     sudo apt-get install npm
    
  2. This application requires Express. Run the command to install express:

     npm install express
    

Starting the Supply Chain API from command-line

  1. In terminal, go to this directory i.e. examples/supplychain-app/quorum/express_nodeJS/ directory and install the dependencies

     npm install
    
  2. You will need a minimum of 3 nodes running for the supply chain app. The manufacturer, carrier and warehouse will each have a node. Rename the PartyAEnv.list file to .env

     mv PartyAEnv.list .env
     
    
  3. Update the .env file with correct parameters and run the following command to start the node for the manufacturer:

     node app.js
    
  4. Open a new terminal, go to this directory i.e. examples/supplychain-app/quorum/express_nodeJS/ directory. Run the command below to start another node. This node will be for the carrier. Use another address from the Ganache CLI that have not been used already. Update the NODE_SUBJECT to reflect the carrier.

     PORT=8081 NODE_IDENTITY=0x.... NODE_ORGANIZATION=Carrier NODE_ORGANIZATIONUNIT=Carrier node app.js 
    
  5. Repeat step 5. This node is for the warehouse.

     PORT=8082 NODE_IDENTITY=0x... NODE_ORGANIZATION=PartyC NODE_ORGANIZATIONUNIT=Warehouse node app.js
    

Once you have 3 nodes running, you should be ready to able to use Postman to test the APIs.

Docker Deployment

The deployment has been made easy for Docker. The provided dockerfile will create the image that can be run multiple times by passing the envfile.

The following command will create the image called supplychain_quorum and then run the service on port 8080 for the manufacturer. Edit the PartyAEnv.list with correct environment parameters according to your Quorum network first.

docker build -t supplychain_quorum .
docker run --detach --env-file PartyAEnv.list -p 8080:3000 supplychain_quorum

Similarly use PartyBEnv.list and PartyCEnv.list env files to run the service for Carrier and Warehouse. Remember to use a different host port (instead of 8080, use 8082 and 8084).

Available Api

The list of all supplychain api requests are listed below:

General
Get /api/v1/{trackingID}/history
Return format
    [
        {
            "party": "0xcCdd8AA32944992B7489718e213c9547F1640980,O=Manufacturer,OU=Manufacturer,L=47.38/8.54/Zurich,C=CH",
            "time": 1549565435354,
            "location": "O=Manufacturer,OU=Manufacturer,L=47.38/8.54/Zurich,C=CH"
        },
        {...}
    ]
Purpose:

This maps the custodian changes on the ledger to a list of objects with the timestamp of custodian change and new custodian

Other

Tracking ID is a passed in string and must be a valid UUID (java.util.uuid)

Get /api/v1/{trackingID}/scan
Return format
    {
        "status": "owned"
    }
Purpose:

This checks trackable states and sees whether the any state associate to that tracking ID exists and if so returned if you currently own it.

Other:

Tracking ID is a passed in string and must be a valid UUID (java.util.uuid). The different states are owned, unowned, and new.

Get /api/v1/node-organization
Return format
    {
        "organization": "Manufacturer"
    }
Purpose:

This checks the nodes organization name

Other:

N/A

Get /api/v1/node-organizationUnit
Return format
    {
        "organizationUnit": "manufacturer"
    }
Purpose:

This checks the nodes organization unit name. In the front end this allows the user to access a few different APIs.

Other:

N/A

Products
Get /api/v1/product
Return format
    [{
        "productName": "Insulin",
        "health": null,
        "sold": false,
        "recalled": false,
        "misc": {
            "name": "Expensive Insulin"
        },
        "custodian": "0xaEd9744684F9185AaF82A235BBBBb5408D881592,O=Warehouse,OU=Warehouse,L=42.36/-71.06/Boston,C=US",
        "trackingID": "53116d75-e884-4d21-bbd8-057a144a30c5",
        "timestamp": 1552583510960,
        "containerID": "17219ad9-3e8b-4c79-ab55-79f6ada4a2d6",
        "linearId": {
            "externalId": null,
            "id": "53116d75-e884-4d21-bbd8-057a144a30c5"
        },
        "participants": [
            "0xccdd8aa32944992b7489718e213c9547f1640980,O=Manufacturer,OU=Manufacturer,L=47.38/8.54/Zurich,C=CH",
            "0x71402dd5e14d8d17ce9d051aded639a2cbcaa78b,O=Carrier,OU=Carrier,L=51.50/-0.13/London,C=GB",
            "0xaed9744684f9185aaf82a235bbbbb5408d881592,O=Warehouse,OU=Warehouse,L=42.36/-71.06/Boston,C=US"
            "0xafe4671684f9185aaf82a235bbbbb5408d881592,OU=Store, O=PartyD,L=40.73/-74/New York,C=US"
        ]
    }]
Purpose:

This gets back a list of all products available to node

Other:

N/A

Get /api/v1/product/{trackingID}
Return format
    {
        "productName": "Insulin",
        "health": null,
        "sold": false,
        "recalled": false,
        "misc": {
            "name": "Expensive Insulin"
        },
        "custodian": "0xaEd9744684F9185AaF82A235BBBBb5408D881592,O=Warehouse,OU=Warehouse,L=42.36/-71.06/Boston,C=US",
        "trackingID": "53116d75-e884-4d21-bbd8-057a144a30c5",
        "timestamp": 1552583510960,
        "containerID": "17219ad9-3e8b-4c79-ab55-79f6ada4a2d6",
        "linearId": {
            "externalId": null,
            "id": "53116d75-e884-4d21-bbd8-057a144a30c5"
        },
        "participants": [
            "0xccdd8aa32944992b7489718e213c9547f1640980,O=Manufacturer,OU=Manufacturer,L=47.38/8.54/Zurich,C=CH",
            "0x71402dd5e14d8d17ce9d051aded639a2cbcaa78b,O=Carrier,OU=Carrier,L=51.50/-0.13/London,C=GB",
            "0xaed9744684f9185aaf82a235bbbbb5408d881592,O=Warehouse,OU=Warehouse,L=42.36/-71.06/Boston,C=US"
            "0xafe4671684f9185aaf82a235bbbbb5408d881592,OU=Store, O=PartyD,L=40.73/-74/New York,C=US"
        ]
    }
Purpose:

This gets back the single product with tracking id from url param

Other:

N/A

POST /api/v1/product
Request format
    {
    "productName":"Dextrose",
    "misc": {"name":"Expensive Dextrose"},
    "trackingID": "0d15d7b8-caaa-468d-8b83-aae049b40f46",
    "counterparties": ["PartyA","PartyB","PartyC","PartyD"]
    }
Return format
    {
        "generatedID": "0d15d7b8-caaa-468d-8b83-aae049b40f46"
    }
Purpose:

This POST adds the product to the ledger and returns the trackingID back. It also send the copy to all other counterparties allowed to view and handle the product.

Other:

This data is parsed from a QR code on the front end. The misc field is customizable and doesnt need anything or can be a mapping of any key to any value. Used to store other metadata.

NOTE: For Quorum, the calling party must be in the "counterparties" list in the request.

PUT /api/v1/product/{trackingID}/custodian
Return format
"0d15d7b8-caaa-468d-8b83-aae049b40f46"
Purpose:

This is used to update custodian to node hitting the endpoint

Other:

N/A

Get /api/v1/product/containerless
Return format
    [{
        "productName": "Insulin",
        "health": null,
        "sold": false,
        "recalled": false,
        "misc": {
            "name": "Expensive Insulin"
        },
        "custodian": "0xaEd9744684F9185AaF82A235BBBBb5408D881592,O=Warehouse,OU=Warehouse,L=42.36/-71.06/Boston,C=US",
        "trackingID": "53116d75-e884-4d21-bbd8-057a144a30c5",
        "timestamp": 1552583510960,
        "containerID": "",
        "linearId": {
            "externalId": null,
            "id": "53116d75-e884-4d21-bbd8-057a144a30c5"
        },
        "participants": [
            "0xccdd8aa32944992b7489718e213c9547f1640980,O=Manufacturer,OU=Manufacturer,L=47.38/8.54/Zurich,C=CH",
            "0x71402dd5e14d8d17ce9d051aded639a2cbcaa78b,O=Carrier,OU=Carrier,L=51.50/-0.13/London,C=GB",
            "0xaed9744684f9185aaf82a235bbbbb5408d881592,O=Warehouse,OU=Warehouse,L=42.36/-71.06/Boston,C=US"
            "0xafe4671684f9185aaf82a235bbbbb5408d881592,OU=Store, O=PartyD,L=40.73/-74/New York,C=US"
        ]
    }]
Purpose:

This gets back a list of all products available to node which are containerless

Other:

N/A

Containers
Get /api/v1/container
Return format
    [{
        "health": null,
        "sold": false,
        "recalled": false,
        "misc": {
            "name": "Pharma Insulin container"
        },
        "custodian": "OU=Store, O=PartyD, L=40.73/-74/New York, C=US",
        "trackingID": "17219ad9-3e8b-4c79-ab55-79f6ada4a2d6",
        "timestamp": 1552583510960,
        "containerID": null,
        "contents": [
             "53116d75-e884-4d21-bbd8-057a144a30c5",
             "0d15d7b8-caaa-468d-8b83-aae049b40f46"
        ],
        "linearId": {
            "externalId": null,
            "id": "2059484c-0c3b-43a7-9604-4a61d3039639"
        },
         "participants": [
            "OU=Carrier, O=PartyB, L=51.50/-0.13/London, C=US",
            "OU=Warehouse, O=PartyC, L=42.36/-71.06/Boston, C=US",
            "OU=Store, O=PartyD, L=40.73/-74/New York, C=US",
            "OU=Manufacturer, O=PartyA, L=47.38/8.54/Zurich, C=CH"
            ]
        }]
Purpose:

This gets back a list of all containers available to node

Other:

N/A

POST /api/v1/container
Request format
    {
    "misc": {"name": "Pharma Insulin container"},
    "trackingID": "17219ad9-3e8b-4c79-ab55-79f6ada4a2d6",
    "counterparties": ["PartyA", "PartyB","PartyC","PartyD"]
    }
Return format
    {
        "generatedID": "17219ad9-3e8b-4c79-ab55-79f6ada4a2d6"
    }
Purpose:

This adds the container to the ledger and returns the trackingID back. It also send the copy to all other counterparties allowed to view and handle the container.

Other:

This data is parsed from a QR code on the front end. The misc field is customizable and doesnt need anything or can be a mapping of any key to any value. Used to store other metadata.

NOTE: For Quorum, the calling party must be in the "counterparties" list in the request.

Get /api/v1/container/{trackingID}
Return format
    {
        "health": null,
         "sold": false,
        "recalled": false,
        "misc": {
            "name": "Pharma Insulin container"
        },
        "custodian": "OU=Store, O=PartyD, L=40.73/-74/New York, C=US",
        "trackingID": "17219ad9-3e8b-4c79-ab55-79f6ada4a2d6",
        "timestamp": 1552583510960,
        "containerID": null,
        "contents": [
             "53116d75-e884-4d21-bbd8-057a144a30c5",
             "0d15d7b8-caaa-468d-8b83-aae049b40f46"
        ],
        "linearId": {
            "externalId": null,
            "id": "2059484c-0c3b-43a7-9604-4a61d3039639"
        },
         "participants": [
            "OU=Carrier, O=PartyB, L=51.50/-0.13/London, C=US",
            "OU=Warehouse, O=PartyC, L=42.36/-71.06/Boston, C=US",
            "OU=Store, O=PartyD, L=40.73/-74/New York, C=US",
            "OU=Manufacturer, O=PartyA, L=47.38/8.54/Zurich, C=CH"
        ]
    }
Purpose:

This gets back the container with the id passed in the url param.

Other:

N/A

PUT /api/v1/container/{trackingID}/custodian
Return format
"17219ad9-3e8b-4c79-ab55-79f6ada4a2d6"
Purpose:

This is used to update custodian to node hitting the endpoint

Other:

N/A

PUT /api/v1/container/{containerTrackingID}/package
Request format
    {
        "contents":"{productTrackingID}"
    }
Return format
"{containerTrackingID}"
Purpose:

This is used to add a product to a container

Other:

Currently only works one at a time but can be modified (should be) to allow multiple.

PUT /api/v1/container/{containerTrackingID}/unpackage
Request format
    {
        "contents":"{productTrackingID}"
    }
Return format
"{containerTrackingID}"
Purpose:

This is used to remove a product from a container

Other:

Currently only works one at a time but can be modified (should be) to allow multiple.

Tag summary

Content type

Image

Digest

Size

115.1 MB

Last updated

almost 5 years ago

docker pull hyperledgerlabs/supplychain_quorum:express_app_latest