Taxonomy Icon

Blockchain

Learn the process of using IBM Blockchain Platform’s VSCode extension to streamline the process of developing, testing, and deploying a smart contract. Once you finish this tutorial, you will understand how to quickly develop, demo, and deploy your blockchain application on a local Hyperledger Fabric network using VSCode. This tutorial assumes some basic understanding of Hyperledger Fabric.

Watch the videos

Learning objectives

  • Install the IBM Blockchain Platform VSCode extension
  • Create a new JavaScript smart contract
  • Package a smart contract
  • Create, explore, and understand a Hyperledger Fabric network
  • Deploy the smart contract on a local Hyperledger Fabric instance
  • Use a Node.js SDK to interact with the deployed smart contract package

Prerequisites

You will need the following installed in order to use the extension:

If you are using Windows, you must also ensure the following:

  • Your version of Windows supports Hyper-V and Docker:
    • Windows 10 Enterprise, Pro, or Education with 1607 Anniversary Update or later
  • Docker for Windows is configured to use Linux containers (this is the default)
  • You have installed the C++ Build Tools for Windows from windows-build-tools
  • You have installed OpenSSL v1.0.2 from Win32 OpenSSL
    • Install the normal version, not the version marked as “light”
    • Install the Win32 version into C:\OpenSSL-Win32 on 32-bit systems
    • Install the Win64 version into C:\OpenSSL-Win64 on 64-bit systems

You can check your installed versions by running the following commands from a terminal:

  • node --version
  • npm --version
  • yo --version
  • docker --version
  • docker-compose --version

Estimated time

After the prerequisites are installed, this should take approximately 30-45 minutes to complete.

Steps

  1. Get started
  2. Create a new smart contract project
  3. Modify the smart contract
  4. Package the smart contract
  5. Install the smart contract
  6. Instantiate the smart contract
  7. Import the certificate and key
  8. Add an identity
  9. Update the network ports
  10. Invoke the smart contract
  11. Update the smart contract
  12. Query the ledger

Step 1. Get started

packageFile

The first thing you need to do is to install the IBM Blockchain Platform VSCode extension. To do this, you need to install the latest version of VSCode; to see if you have the latest VSCode extension, go to Code > Check for Updates. If VSCode crashes at this point (which it did for me), it likely means you don’t have the latest version. If your VSCode crashes, check the troubleshooting section below. Otherwise, update your VSCode, and once you’re done, click on extensions in the sidebar on the left side of your screen. At the top, search the extension marketplace for IBM Blockchain Platform. Click Install and then click reload. Now you should be all set to use the extension!

Step 2. Create a new smart contract project

packageFile

To create a smart contract project:

  1. Click on your newly downloaded IBM Blockchain Platform extension. It should be the extension all the way at the bottom of the left sidebar.
  2. Next, use the keyboard shortcut Shift + CMD + P to bring up the command pallete. Choose IBM Blockchain Platform: Create Smart Contract Project from the dropdown.
  3. Click JavaScript from the dropdown.
  4. Click New Folder, and name the project what you want. I named mine demoContract.
  5. Click Create and then Open your new folder which you just created. Next, from the dropdown, click Add to Workspace.
  6. Once the extension is done packaging your contract, you can open the lib/my-contract.js file to see your smart contract code scaffold. Nice job!

Step 3. Modify the smart contract

packageFile

Inside your lib/my-contract.js file, go ahead and copy and paste this code:

'use strict';

const { Contract } = require('fabric-contract-api');

class MyContract extends Contract {

  //update ledger with a greeting to show that the function was called
  async instantiate(ctx) {
    let greeting = { text: 'Instantiate was called!' };
    await ctx.stub.putState('GREETING', Buffer.from(JSON.stringify(greeting)));
  }

  //take argument and create a greeting object to be updated to the ledger
  async transaction1(ctx, arg1) {
    console.info('transaction1', arg1);
    let greeting = { text: arg1 };
    await ctx.stub.putState('GREETING', Buffer.from(JSON.stringify(greeting)));
    return JSON.stringify(greeting);
  }

}

module.exports = MyContract;

Note: the .gifs may not exactly match the above smart contract, but this is the one you should have in your lib/my-contract.js file now!

Let’s examine the functions you just defined. The instantiate function creates a greeting object and then stores that on the ledger with the key GREETING. The transaction1 function takes the Hyperledger Fabric context and one argument, arg1, which is used to store a greeting as defined by the user. The ctx.stub.putState method is used to record the greeting on the ledger and then you return that object back. Save the file and proceed!

Step 4. Package the smart contract

packageFile

Now that you have created your smart contract and understand which functions you’ve defined, it’s time to package it so you can install it on a peer.

  1. Open the command pallete with Shift + CMD + P and select package smart contract.
  2. In the left sidebar, click on the IBM Blockchain Platform icon (it looks like a square). In the top-left corner, you will see all of your smart contract packages. You should see demoContract@0.0.1 if everything went well.

Step 5. Install the smart contract

packageFile

Ok, you’re more than halfway there. Now for the fun part! Let’s install this contract on the peer! To do this, you must first connect to a Hyperledger Fabric network. The network that comes with the VSCode extension is perfect for development — it offers the minimal resources to develop and test your contract.

The following Docker containers are started on your local machine, each with a different role in the network: Orderer, Certificate Authority, CouchDB, and Peer.

To start your network, look at your IBM Blockchain Platform extension, at the bottom-right corner where it says Blockchain Connections.

  1. You should see local_fabric. Go ahead and click that. It should automatically run a script and you should see the following output:
    Starting fabricvscodelocalfabric_orderer.example.com_1 ... done
    Starting fabricvscodelocalfabric_ca.example.com_1      ... done
    Starting fabricvscodelocalfabric_couchdb_1             ... done
    Starting fabricvscodelocalfabric_peer0.org1.example.com_1 ... done
    
  2. Click the local_fabric connection again. Now that it’s up and running, it should take you to your channel view, which should show one channel, named mychannel. Click on that.
  3. This will expand your channel and show the peers and smart contracts. Click on peers and you should see peer0.org1.example.com. Right-click on that peer, and click on Install Smart Contract.
  4. The extension will ask you which package to install: Choose demoContract@0.0.1. That’s it! Nice job!

Step 6. Instantiate the smart contract

packageFile

This is the real test — will your smart contract instantiate properly? Let’s find out…

  1. From the IBM Blockchain extension, in the bottom-left corner, under Blockchain Connections, right-click on mychannel and then on Instantiate / Upgrade Smart Contract.
  2. The extension will then ask you which contract and version to instantiate — choose demoContract@0.0.1.
  3. The extension will then ask you which function to call — type in instantiate.
  4. Next, it will ask you for the arguments. There are none, so just hit enter.

The extension will do some work, and then in the bottom-right corner you should see that the contract was successfully instantiated. Hooray!!

Step 7. Import the certificate and key

packageFile

At this point, you need to start interacting a bit more closely with your Fabric instance. You’ll need to prove to the certificate authority that you are allowed to create a digital identity on the network, and that is by showing the certificate authority your certificate and private key. For the sake of keeping this tutorial as short as possible, I have a GitHub repo with all the certs, keys, and scripts you will work with, so go ahead and git clone this repo in a directory of your choice, but outside the demoContract directory.

  1. In a terminal, navigate to a directory to clone the GitHub repository into.
  2. Clone the GitHub repository by using the following command:
    $ git clone https://github.com/horeaporutiu/VSCodeLocalNetwork.git
    
  3. Import this folder into your VSCode workspace by right-clicking an empty space under your smart contract directory in VSCode and selecting Add folder to workspace. Find the recently cloned folder VSCodeLocalNetwork and double-click it.
  4. Skim the cert and key files — they contain your certificate and private key which will be used to request an identity from the certificate authority. There is also an addIdentity.js script which has the following code:
'use strict';

// Bring key classes into scope, most importantly Fabric SDK network class
const fs = require('fs');
const { FileSystemWallet, X509WalletMixin } = require('fabric-network');

// A wallet stores a collection of identities for use
const wallet = new FileSystemWallet('./_idwallet');

async function main(){

    // Main try/catch block
    try {

        // define the identity to use
        const cert = fs.readFileSync('./cert').toString();
        const key = fs.readFileSync('./key').toString();
        const identityLabel = 'User1@org1.example.com';

        // prep wallet and test it at the same time
        await wallet.import(identityLabel, X509WalletMixin.createIdentity('Org1MSP', cert, key));

    } catch (error) {
        console.log(`Error adding to wallet. ${error}`);
        console.log(error.stack);
    }
}

main().then(()=>{
    console.log('done');
}).catch((e)=>{
    console.log(e);
    console.log(e.stack);
    process.exit(-1);
});

This code creates an identity by passing in your certificate and private key. Notice that you are using the fabric-network NPM package to call the createIdentity method, and then using the import function to add that identity to your wallet. The most important line in this file is await wallet.import(identityLabel, X509WalletMixin.createIdentity('Org1MSP', cert, key));, which actually creates a new MSP identity using your cert and key file. This Membership Service Provider (MSP) identity will be able to connect to the network and invoke smart contracts.

Step 8. Add an Identity

packageFile

Now that you have an identity that can interact with your network, you need to to run npm install to install all the dependencies that are needed to connect to your local Fabric network.

  1. Run npm install in the VSCodeLocalNetwork.
  2. Then, run node addIdentity. You should see that this command creates a new folder called _idwallet and populates that folder with the MSP identity, which in this case goes by the name of User1@org1.example.com. Nice job!

Step 9. Update the network ports

packageFile

  1. Next, open the network.yaml in the VSCodeLocalNetwork folder. You will use this file to connect to your Docker containers running locally.

  2. To see your Docker containers running locally, run docker ps. Your output should look something like this:

packageFile

Important note: Your ports will differ from those shown.

  1. Next, look for fabric-peer,fabric-ca, and fabric-orderer in the docker ps logs. It may be hard to read, so be careful here. The 5-digit number is the port number that you need to update in the appropriate place in the network.yaml file. Update the peer, CA, and orderer’s URL field as shown in the preceding .gif.

In the example above the ports in network.yaml would be set as follows:

orderers:
  orderer.example.com:
    url: grpc://localhost:32823

Then the peer:

peers:
  peer0.org1.example.com:
    # this URL is used to send endorsement and query requests
    url: grpc://localhost:32827

Then the CA:

certificateAuthorities:
  ca-org1:
    url: http://localhost:32822
  1. Great job! Save the file.

Step 10. Invoke the smart contract

packageFile

Ok, so you’ve instantiated your contract and created your identity, so now what? Well now, it’s time to actually invoke the functions in your contract! To do this, you will need to invoke a script from your VSCodeLocalNetwork directory.

  1. From your git clone, you should have a file called invoke.js. Let’s examine this file.

  2. After you create an instance of the fabric-network, you connect to the network with the following code:

await gateway.connect(connectionProfile, connectionOptions);

Notice here that the connection profile is the network.yaml file that you updated in the previous step, and the connectionOptions is an object that contains the credentials from your _idwallet directory.

  1. After you connect to the network, you need to specify the channel to connect to, which in this case happens to be mychannel. This line connects to your channel:
const network = await gateway.getNetwork('mychannel');
  1. Your channel may have many contracts installed, so in the next line, you need to specify which contract to invoke. In this case, it would be demoContract.
const contract = await network.getContract('demoContract');
  1. The final part of your script picks which function to invoke and specifies the arguments. In this case, you are invoking transaction1 with an arg of hello, as can be seen here:
let response = await contract.submitTransaction('transaction1', 'hello');
  1. Now you can run the script with this command:
$ node invoke.js

If you get an error, check your network.yaml file and make sure the ports are the same as shown in your logs from the docker ps command.

If all goes well, you should see the following output:

VSCodeLocalNetwork$ node invoke.js
Connected to Fabric gateway.
Connected to mychannel.

Submit hello world transaction.
info: [TransactionEventHandler]: _strategySuccess: strategy success for transaction "9bf00460721a9d42dfe0d3bf93151f10be8b0a57011d4b24262ef03d5a33ee5e"

{ text: 'hello' }
Disconnect from Fabric gateway.
done

Woo!! That’s it! Nice job!

Step 11. Update the smart contract

packageFile

In the previous step, you updated the ledger by using the putState API, passing in a key and a value. The key happened to be “GREETING” and the value happened to be the object:

{
  text: 'hello'
}

The last thing you should learn is how to query — how to retrieve data from the ledger. You will do this by using the getState API, which takes in a key and returns the value associated with that key, if it finds it.

Let’s add a query function to the demoContract.

  1. Copy and paste the following code into your lib/my-contract.js file:
'use strict';

const { Contract } = require('fabric-contract-api');

class MyContract extends Contract {

  //update ledger with a greeting 
  async instantiate(ctx) {
    let greeting = { text: 'Instantiate was called!' };
    await ctx.stub.putState('GREETING', Buffer.from(JSON.stringify(greeting)));
  }

  //add a member along with their email, name, address, and number
  async addMember(ctx, email, name, address, phoneNumber) {
    let member = {
      name: name,
      address: address,
      number: phoneNumber
    };
    await ctx.stub.putState(email, Buffer.from(JSON.stringify(member)));
    return JSON.stringify(member);
  }

  // look up data by key
  async query(ctx, key) {
    console.info('querying for key: ' + key  );
    let returnAsBytes = await ctx.stub.getState(key);
    let result = JSON.parse(returnAsBytes);
    return JSON.stringify(result);
  }

}

module.exports = MyContract;

The code adds an addMember function, which takes in arguments from the user such as email, name, address, and phone number, and saves that data on the ledger as a key-value pair.

This code also adds a query function — this function takes in one argument, which is the key to look up. The function returns the value associated with a given key, if there is any.

  1. Update the package.json file such that line 3, which contains the version number, now reads:

      "version": "0.0.2",
    

    Save the file.

  2. After you have updated package.json, go back and follow steps 3 and 4 to package and install your new smart contract.

  3. To upgrade your existing smart contract to your new version, in the bottom left corner of your IBM Blockchain extension, expand the Instantiated Smart Contract link, and then right-click on demoContract and choose Upgrade Smart Contract. If all goes well, you should get a notification in the bottom right corner saying Successfully upgraded smart contract. packageFile

  4. In your invoke.js file, change the following line:

    let response = await contract.submitTransaction('transaction1', 'hello');
    

    to the following:

    let response = await contract.submitTransaction('addMember', 'ginny@ibm.com', 'Ginny Rometty', 'Wall Street, NY', '1234567890');
    
  5. Save the file, and run the following command:

$ node invoke.js

You should get the following output:

  VSCodeLocalNetwork$ node invoke.js
  Connected to Fabric gateway.
  Connected to mychannel.
  Submit hello world transaction.
  info: [TransactionEventHandler]: _strategySuccess: strategy success for transaction "d97fa4844c3135153228200578553423df3c8ff59fc54506c9421e16d7cc9a0b"
  { name: 'Ginny Rometty',
    address: 'Wall Street, NY',
    number: '1234567890',
    email: 'ginny@ibm.com' }
  Disconnect from Fabric gateway.
  done
  1. In your invoke.js file, add one more member:
let response = await contract.submitTransaction('addMember', 'arvind@ibm.com', 'Arvind Krishna', 'Broadway Street, NY', '1231231111');

Save the file and invoke the smart contract (run node invoke.js). You should get output similar to the one above, but with the new data about Arvind.

Step 12. Query the ledger

packageFile

After you have added some objects on the ledger, it’s time to query the ledger to see if your data is properly stored on the CouchDB instance of your local Fabric network.

  1. Take a look at your query.js file. It’s very similar to your invoke.js file, except it has a few key differences:
const channel = network.getChannel();

//set up your request - specify which chaincode, which function, and which arguments
let request = { chaincodeId: 'demoContract', fcn: 'query', args: ['GREETING'] };

//query the ledger by the key in the args above
let resultBuffer = await channel.queryByChaincode(request);

The main difference is that in this file, you use the queryByChaincode API, which reads from the ledger. This is very important. In your invoke.js file, you submit transactions to the ledger, which will all get written to the ledger but here, in your query.js file, you will not update the ledger.

  1. Run the script, to find the value stored in the GREETING variable:
$ node query.js

You should get the following output:

Connected to Fabric gateway.
{ text: 'Instantiate was called!' }
Disconnect from Fabric gateway.
done
  1. Next, you’ll query for Ginny Rometty. Change the following line:
let request = { chaincodeId: 'demoContract', fcn: 'query', args: ['GREETING'] };

to this:

let request = { chaincodeId: 'demoContract', fcn: 'query', args: ['ginny@ibm.com'] };

Your output should be as follows:

VSCodeLocalNetwork$ node query.js
Connected to Fabric gateway.
{ address: 'Wall Street, NY',
  email: 'ginny@ibm.com',
  name: 'Ginny Rometty',
  number: '1234567890' }
Disconnect from Fabric gateway.
done
  1. Lastly, let’s query for Arvind. Modify the request to be as follows:
let request = { chaincodeId: 'demoContract', fcn: 'query', args: ['arvind@ibm.com'] };

The output should be similar to the one above, except with Arvind’s data.

Summary

Nice work! You learned how to create, package, install, instantiate, and invoke a smart contract using Hyperledger’s newest APIs. At this point, you can focus on developing your smart contract and updating your my-contract.js file knowing that you have taken care of the networking aspects of blockchain. You can also successfully invoke and update your ledger using just VSCode, Node.js, and Docker. Please, please, please reach out to me if there are bugs — comment on this post and I will fix them. Thanks so much for reading this tutorial. I hope you enjoyed it! Horea Blockchain out!