🚧🚧🚧 This pattern is currently being updated - it uses depracated components. Use at your own risk! 🚧🚧🚧 In this pattern, we will be creating a local Hyperledger Fabric network using the IBM Blockchain Platform extension for VSCode which makes it easy to start developing smart contracts.
The solution that we will be creating is an asset lifecycle and tracking solution that keeps a record of the asset from creation to deletion. Also, we will be creating and managing asset leases which keep track of the lease terms in a lease agreement such as end date, price, and deposit amount.
For the IoT integration, we will be leveraging the IBM Watson IoT Platform to handle device scanning at various locations as the asset is being transferred. Instead of having an actual physical device, we will be creating a web app pretending to be a device which will trigger these scans and notify a locally node.js app to invoke the updateAssetLocation transaction.
After completing this pattern you will understand how to:
In this demo scenario we have three participants: a manufacturer, a vendor, and a contractor.
The asset being stored in the ledger has the following properties:
The asset lease being stored in the ledger has the following properties:
To start off, we are going to create the simulated IoT device which will invoke the updateAssetLocation with the location where the device was "scanned". We will be using the IBM Watson IoT Platform to facilitate the communicaton from our virtual device to a local IoT service which will be listening for published device events.
For the code used to build this virtual device, we will be using a framework called Node-Red which is a low code environment which allows for drag and drop of preconfigured nodes to easily build applications.
IBM Cloud has a starter kit for IoT applications that comes with a Node-Red application and an instance of the IBM Watson IoT Platform service already bound to it.
Click create. This creation process will take a bit.
Once the application is deployed, click on Visit App URL at the top of the page to go to the application.
The first time you open a Node-Red application you have to go through the initial set up wizard. To start, create an admin username and password. You can also select the checkbox to give read access to anybody that visit's your app.
When done with the wizard you should be taken to the application. Click on the red button that says Go to your Node-RED flow editor. The page that you are brought to is called the Canvas which is where you drag and drop your nodes. The left pane that holds all the nodes is called the palette.
To make any changes you will need to log in with the admin account created during set up. Click on the sillouette at the top right of the page and click log in. Then, enter your username and password to log in.
You may notice that this application already comes with some starter code, go ahead and select it all with your curser by clicking and draging and then press your delete key.
Then paste in the contents of the flow.json file from this repo and click Import.
Now that we have our flow imported, we now need to use the IBM Watson IoT Platform to facilitate communication between the virtual device and the local IoT application.
Connect with the IBM Watson IoT PlatformIt's important to copy the Authentication Token as you will not be able to retrieve it once you leave the page.
Now we need to register an application with the platform to generate an API key
On the Apps, page, click on Generate API Key at the top right of the page.
Add a description if you wish, then click on Next
On the new page, select Standard Application as the Role
Click Generate Key
Once the API Key has been added, copy both the API Key and the Authentication Token to a seperate doc.
Again, just like with the device credentials, you cannot retrieve the token once you leave the page. Be sure to have it copied somewhere.
Now that we have our device registered and the credentials saved, let's return to our code editor.
Starting the local Hyperledger Fabric networkBefore we go any further, we need to start our local blockchain network. Luckily for us, there is a plug in for VSCode called the IBM Blockchain Platform extension that allows us to get a network up and running with the push of a button.
Open up Visual Studio Code
If you don't already have it, install the IBM Blockchain Platform extension in VSCode using the instructions found here
Once the extension is installed, click on the IBM Blockchain Platform icon on the left toolbar of VSCode.
Your local network will then be spun up in docker containers on your machine. We will be using this local networks to deploy our smart contracts to.
Creating the Logspout ContainerThroughout this workshop we may need to see what the output of certain actions against the Hyperledger Fabric network are. To see this output we will be implementing a special container called the logspout container. This container will monitor all log output from all containers in a certain docker network. In this case, we can see what each container in our Hyperledger Fabric network is saying which will help with debuging.
git clone https://github.com/IBM/assetTracking.git
In order to start using the chaincode we need to package, install, and instantiate it first.
In the new dialog window, find the org1/contract folder in this repo and click Add. You should now see contract appear in the file explorer.
Then, click on the IBM Blockchain Platform extension on the left side of VSCode.
Find the Smart Contract Packages section, hover your mouse over it, and click on the three dot menu. Then select package a smart contract project
A new prompt should appear at the top of VSCode asking to choose a workspace folder to package. Select contract
You now have a smart contract package named asset-tracking with a version number following it. Everytime you make a change to the smart contract, you must increase the version number in package.json and repackage the smart contract.
Now that we have the smart contract packaged we need to install the smart contract onto a peer.
Installing and InstantiatingGetting the smart contract on to a Hyperledger Fabric network involves two key steps: Install and Instantiate.
Install is simply the process of putting the smart contract onto a peer. Although the peer holds the smart contract, the contract does not execute on the peer. This is where the instantiation process comes in.
Instantiation is performed on a channel by a peer and it is the process of creating a chaincode container to execute logic found in smart contracts. Having the chaincode execute in a separate container ensures security and stability as chaincode execution does not have access to the peer file system and cannot bring the peer down in the event of a crash.
In the prompts that come up select peer0.org1.example.com
Then select the smart contract that we just packaged which should be asset-tracking@1.0.0
Your smart contract is now installed. Next we need to instantiate it.
In the prompt that comes up, select mychannel
A prompt should appear at the top of VSCode asking which smart contract to instantiate. Select the one that was just installed.
The next prompt should ask for a function to call. Enter instantiate and press enter.
Then, a new prompt will ask for arguments to pass. We don't have any to pass in so just press enter.
While the smart contract is instantiating you can see how the process is going by checking on the logspout container which should be running in a terminal window.
If there are any errors during instantiation, you can see what went wrong in the logspout container.
Now we are ready to test out transactions.
Invoking transactions with the IBM Blockchain Platform VSCode ExtensionAnother handy function of the IBM Blockchain Platform VSCode extenstion is the ability to invoke transactions without having to write an application to do so.
This will allow us to intract with our local network through the eyes of the organization admin user.
You can right click on a transaction and select submit transaction to invoke the transaction in the contract. Once you select submit transaction you will be asked for arguments to pass in. You may need to check out the AssetContract.js file to see what transactions require which arguments.
Let's test out some transactions. Submit the following transactions with the respective arguments:
At the moment, our ledger doesn't have any information, let's populate it with some dummy data.
Right click on setUpDemo and select submit transaction
When asked for agruments, press enter.
Next let's query the ledger and see what was added. Right click on the queryAll transaction and select evaluate transaction. When asked for arguments, press enter.
Check out the terminal window that was tailing the logs in the logspout container to see the results of the query.
Invoking transactions with the Node SDKIn this section we will be invoking the transactions defined in assetContract using the the fabric-network module. This is a new module introduced in Hyperledger Fabric 1.4.
In the application folder you will find invoke.js. In this file we will be copying and pasting the code to invoke transactions and see what the response is.
In between the end of that comment block and the End of transaction invocation section, paste in the code for each transaction mentioned below.
Save the file
Run the following commands
npm install
node invoke.js
We will be following the same transaction order from the previous section on invoking transactions with the VSCode extension.
Using the 5 steps outlined above, invoke a few of the following transactions if you would like to see the SDK in action.
The manufactureAsset transaction creates a new digital asset to be stored on the ledger. Once the transaction is successful, the new asset is returned.
const manufactureResponse = await contract.submitTransaction('manufactureAsset', 'manufacturer1','A-005', 'asset'); let asset = Asset.fromBuffer(manufactureResponse); console.log(asset);
The transferAsset transaction transfers ownership of the asset within the ledger. Returns the transferred asset
const transferResponse = await contract.submitTransaction('transferAsset', "manufacturer1","A-005","manufacturer1","vendor1"); let asset = Asset.fromBuffer(transferResponse); console.log(asset);
The createLease transaction creates a lease which defines the lessee, lessor, and other lease terms. Returns the created lease.
const createLeaseResponse = await contract.submitTransaction('createLease', "L-004","contractor1","vendor1","A-005","manufacturer1","lease","Jan2019","Jan2021","1000.00","1000.00"); let assetLease = AssetLease.fromBuffer(createLeaseResponse); console.log(assetLease);
The transferAsset transaction transfers ownership of the asset within the ledger. Returns the transferred asset
const transferResponse = await contract.submitTransaction('transferAsset', "manufacturer1","A-005","vendor1","contractor1"); let asset = Asset.fromBuffer(transferResponse); console.log(asset);
The returnAsset transaction is invoked when a lessee wants to return the leased asset at the end of the lease. Returns the returned asset and the lease that has ended.
const returnResponse = await contract.submitTransaction('returnAsset', "manufacturer1","A-005","contractor1","vendor1","L-004","Jan2021"); let response = JSON.parse(returnResponse.toString()); let asset = response.asset; let assetLease = response.assetLease; console.log(asset); console.log(""); console.log(assetLease);
The inspectAsset transaction is invoked when the asset has been received and inspected by the vendor. This transaction records the percent of damage to the asset on the lease. Returns the inspected asset and lease.
const inspecteResponse = await contract.submitTransaction('inspectAsset', "manufacturer1","A-005","vendor1","L-004","21"); let response = JSON.parse(inspecteResponse.toString()); let asset = response.asset; let assetLease = response.assetLease; console.log(asset); console.log(""); console.log(assetLease);
The repairAsset transaction is called after the asset has been repaired. Sets the asset condition to Refurbished and the state to Available. Returns the repaired asset.
const repairResponse = await contract.submitTransaction('repairAsset', 'manufacturer1','A-005'); let asset = Asset.fromBuffer(repairResponse); console.log(asset);
The returnDepost transaction records the amount of the depost to be returned to the lessee. This is calculated by looking at the percent of the asset damaged which was recorded in the lease by the inspectAsset transaction and then multiplying the original deposit paid by a percent which corolates with the amount of damage. (e.g. >20% damage to the asset = 80% of the original deposit returned). Returns the lease.
const returnDepositResponse = await contract.submitTransaction('returnDeposit', 'vendor1','L-004'); let assetLease = AssetLease.fromBuffer(returnDepositResponse); console.log(assetLease);Configuring the local IoT Service
Remember that IoT set up that we did earlier? Now let's put it to use. In this section we will be starting a local application that listens for IoT events and updates the ledger. In our case these events will be "scans" from our simulated device.
Now that the app is running, let's test it out.
In this section we will trigger some device events from our simulated device which in turn will invoke the updateAssetLocation transaction and update the asset's location in the ledger.
Open your browser to the Node-Red app that we deployed before. If you closed the tab, go back to the IBM Cloud dashboard and luck under Cloud foundry applications
You should see a bunch of blue nodes with buttons to the left side of them. These nodes are called inject nodes and are used to start flows or inject inforamtion into the payload. In our app, we use them to start the flow to emit a device event to the IoT Platform.
All you need to do is click on the blue button next to the corresponding location that you want to simulate a scan even at.
For example, if you want to simulate the device arriving at the vendor's inspection warehouse at the end of a lease, just click on the inject node next to the orange Inspection Warehouse scan node.
To query the world state database there are two files that we can use to help us out: queryByField.js and queryAll.js.
queryByField.js does just what it says. It queries the world state and only returns assets that match the values for a field such as "currentOwner", "assetType", or "currentOwner". For example, we can use this file to get all assets that are owned by vendor1.
queryAll also does what it says. It returns everything in the world state.
By default, it will return all assets with assetType that equals "asset" which means it will not return leases.
This will return everything in the ledger.
In this lab we did a lot. First we created a virtual device with Node-Red and then configured the IBM Watson IoT Platform and received API credentials. Next we created the logspout container to monitor logs from our Hyperledger Fabric network. After that, we packaged, installed, and instantiated a smart contract on our local Hyperledger Fabric network. This allowed us to test out some of our transactions using the VSCode plugin. Once we were done testing out the transactions we decided to import some identities and start invoking transactions with the Node SDK. Then, we started the local IoT app to start listening for scan events which we then began to send from our Node-Red app. Finally, we queried the world state database using two different query programs.
This code pattern is licensed under the Apache License, Version 2. Separate third-party code objects invoked within this code pattern are licensed by their respective providers pursuant to their own separate licenses. Contributions are subject to the Developer Certificate of Origin, Version 1.1 and the Apache License, Version 2.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4