github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/docs/source/tutorial/commercial_paper.md (about)

     1  # Commercial paper tutorial
     2  
     3  **Audience:** Architects, application and smart contract developers,
     4  administrators
     5  
     6  This tutorial will show you how to install and use a commercial paper sample
     7  application and smart contract. It is a task-oriented topic, so it emphasizes
     8  procedures above concepts. When you’d like to understand the concepts in more
     9  detail, you can read the
    10  [Developing Applications](../developapps/developing_applications.html) topic.
    11  
    12  ![commercialpaper.tutorial](./commercial_paper.diagram.1.png) *In this tutorial
    13  two organizations, MagnetoCorp and DigiBank, trade commercial paper with each
    14  other using PaperNet, a Hyperledger Fabric blockchain network.*
    15  
    16  Once you've set up the test network, you'll act as Isabella, an employee of
    17  MagnetoCorp, who will issue a commercial paper on its behalf. You'll then switch
    18  roles to take the role of Balaji, an employee of DigiBank, who will buy this
    19  commercial paper, hold it for a period of time, and then redeem it with
    20  MagnetoCorp for a small profit.
    21  
    22  You'll act as a developer, end user, and administrator, each in different
    23  organizations, performing the following steps designed to help you understand
    24  what it's like to collaborate as two different organizations working
    25  independently, but according to mutually agreed rules in a Hyperledger Fabric
    26  network.
    27  
    28  * [Set up machine](#prerequisites) and [download samples](#download-samples)
    29  * [Create the network](#create-the-network)
    30  * [Examine the commercial paper smart contract](#examine-the-commercial-paper-smart-contract)
    31  * [Deploy the smart contract to the channel](#deploy-the-smart-contract-to-the-channel)
    32    by approving the chaincode definition as MagnetoCorp and Digibank.
    33  * Understand the structure of a MagnetoCorp [application](#application-structure),
    34    including its [dependencies](#application-dependencies)
    35  * Configure and use a [wallet and identities](#wallet)
    36  * Run a MagnetoCorp application to [issue a commercial paper](#issue-application)
    37  * Understand how DigiBank uses the smart contract in their [applications](#digibank-applications)
    38  * As Digibank, run applications that
    39    [buy](#buy-application) and [redeem](#redeem-application) commercial paper
    40  
    41  This tutorial has been tested on MacOS and Ubuntu, and should work on other
    42  Linux distributions. A Windows version is under development.
    43  
    44  ## Prerequisites
    45  
    46  Before you start, you must install some prerequisite technology required by the
    47  tutorial. We've kept these to a minimum so that you can get going quickly.
    48  
    49  You **must** have the following technologies installed:
    50  
    51    * [**Node**](https://github.com/hyperledger/fabric-sdk-node#build-and-test)
    52      The Node.js SDK README contains the up to date list of prerequisites.
    53  
    54  You **will** find it helpful to install the following technologies:
    55  
    56    * A source code editor, such as
    57      [**Visual Studio Code**](https://code.visualstudio.com/) version 1.28, or
    58      higher. VS Code will help you develop and test your application and smart
    59      contract. Install VS Code [here](https://code.visualstudio.com/Download).
    60  
    61      Many excellent code editors are available including
    62      [Atom](https://atom.io/), [Sublime Text](http://www.sublimetext.com/) and
    63      [Brackets](http://www.sublimetext.com/).
    64  
    65  You **may** find it helpful to install the following technologies as you become
    66  more experienced with application and smart contract development. There's no
    67  requirement to install these when you first run the tutorial:
    68  
    69    * [**Node Version Manager**](https://github.com/creationix/nvm). NVM helps you
    70      easily switch between different versions of node -- it can be really helpful
    71      if you're working on multiple projects at the same time. Install NVM
    72      [here](https://github.com/creationix/nvm#installation).
    73  
    74  ## Download samples
    75  
    76  The commercial paper tutorial is one of the samples in the `fabric-samples`
    77  repository. Before you begin this tutorial, ensure that you have followed the
    78  instructions to install the Fabric [Prerequisites](../prereqs.html) and
    79  [Download the Samples, Binaries and Docker Images](../install.html).
    80  When you are finished, you will have cloned the `fabric-samples` repository that
    81  contains the tutorial scripts, smart contract, and application files.
    82  
    83  ![commercialpaper.download](./commercial_paper.diagram.2.png) *Download the
    84  `fabric-samples` GitHub repository to your local machine.*
    85  
    86  After downloading, feel free to examine the directory structure of `fabric-samples`:
    87  
    88  ```
    89  $ cd fabric-samples
    90  $ ls
    91  
    92  CODEOWNERS			    SECURITY.md			        first-network
    93  CODE_OF_CONDUCT.md		chaincode			        high-throughput
    94  CONTRIBUTING.md			chaincode-docker-devmode	interest_rate_swaps
    95  LICENSE				    ci				            off_chain_data
    96  MAINTAINERS.md			commercial-paper		    test-network
    97  README.md			    fabcar
    98  ```
    99  
   100  Notice the `commercial-paper` directory -- that's where our sample is located!
   101  
   102  You've now completed the first stage of the tutorial! As you proceed, you'll
   103  open multiple command windows for different users and components. For example:
   104  
   105  * To show peer, orderer and CA log output from your network.
   106  * To approve the chaincode as an administrator from MagnetoCorp and as an
   107    administrator from DigiBank.
   108  * To run applications on behalf of Isabella and Balaji, who will use the smart
   109    contract to trade commercial paper with each other.
   110  
   111  We'll make it clear when you should run a command from particular command
   112  window; for example:
   113  
   114  ```
   115  (isabella)$ ls
   116  ```
   117  
   118  indicates that you should run the `ls` command from Isabella's window.
   119  
   120  ## Create the network
   121  
   122  This tutorial will deploy a smart contract using the Fabric test network.
   123  The test network consists of two peer organizations and one ordering organization.
   124  The two peer organizations operate one peer each, while the ordering organization
   125  operates a single node Raft ordering service. We will also use the test network
   126  to create a single channel named `mychannel` that both peer organizations
   127  will be members of.
   128  
   129  ![commercialpaper.network](./commercial_paper.diagram.testnet.png)
   130  *The Fabric test network is comprised of two peer organizations, Org1 and Org2,
   131  and one ordering organization. Each component runs as a Docker container.*
   132  
   133  Each organization runs their own Certificate Authority. The two peers, the
   134  [state databases](../ledger/ledger.html#world-state-database-options), the ordering service node,
   135  and each organization CA each run in their own Docker container. In production
   136  environments, organizations typically use existing CAs that are shared with other
   137  systems; they're not dedicated to the Fabric network.
   138  
   139  The two organizations of the test network allow us to interact with a blockchain
   140  ledger as two organizations that operate separate peers. In this tutorial,
   141  we will operate Org1 of the test network as DigiBank and Org2 as MagnetoCorp.
   142  
   143  You can start the test network and create the channel with a script provided in
   144  the commercial paper directory. Change to the `commercial-paper` directory in
   145  the `fabric-samples`:
   146  ```
   147  cd fabric-samples/commercial-paper
   148  ```
   149  Then use the script to start the test network:
   150  ```
   151  ./network-starter.sh
   152  ```
   153  
   154  While the script is running, you will see logs of the test network being deployed.
   155  When the script is complete, you can use the `docker ps` command to see the
   156  Fabric nodes running on your local machine:
   157  ```
   158  $ docker ps
   159  
   160  CONTAINER ID        IMAGE                               COMMAND                  CREATED              STATUS              PORTS                                        NAMES
   161  a86f50ca1907        hyperledger/fabric-peer:latest      "peer node start"        About a minute ago   Up About a minute   7051/tcp, 0.0.0.0:9051->9051/tcp             peer0.org2.example.com
   162  77d0fcaee61b        hyperledger/fabric-peer:latest      "peer node start"        About a minute ago   Up About a minute   0.0.0.0:7051->7051/tcp                       peer0.org1.example.com
   163  7eb5f64bfe5f        hyperledger/fabric-couchdb          "tini -- /docker-ent…"   About a minute ago   Up About a minute   4369/tcp, 9100/tcp, 0.0.0.0:5984->5984/tcp   couchdb0
   164  2438df719f57        hyperledger/fabric-couchdb          "tini -- /docker-ent…"   About a minute ago   Up About a minute   4369/tcp, 9100/tcp, 0.0.0.0:7984->5984/tcp   couchdb1
   165  03373d116c5a        hyperledger/fabric-orderer:latest   "orderer"                About a minute ago   Up About a minute   0.0.0.0:7050->7050/tcp                       orderer.example.com
   166  6b4d87f65909        hyperledger/fabric-ca:latest        "sh -c 'fabric-ca-se…"   About a minute ago   Up About a minute   7054/tcp, 0.0.0.0:8054->8054/tcp             ca_org2
   167  7b01f5454832        hyperledger/fabric-ca:latest        "sh -c 'fabric-ca-se…"   About a minute ago   Up About a minute   7054/tcp, 0.0.0.0:9054->9054/tcp             ca_orderer
   168  87aef6062f23        hyperledger/fabric-ca:latest        "sh -c 'fabric-ca-se…"   About a minute ago   Up About a minute   0.0.0.0:7054->7054/tcp                       ca_org1
   169  ```
   170  
   171  See if you can map these containers to the nodes of the test network (you may
   172  need to horizontally scroll to locate the information):
   173  * The Org1 peer, `peer0.org1.example.com`, is running in container `a86f50ca1907`
   174  * The Org2 peer, `peer0.org2.example.com`, is running in container `77d0fcaee61b`
   175  * The CouchDB database for the Org1 peer, `couchdb0`, is running in container `7eb5f64bfe5f`
   176  * The CouchDB database for the Org2 peer, `couchdb1`, is running in container `2438df719f57`
   177  * The Ordering node, `orderer.example.com`, is running in container `03373d116c5a`
   178  * The Org1 CA, `ca_org1`, is running in container `87aef6062f23`
   179  * The Org2 CA, `ca_org2`, is running in container `6b4d87f65909`
   180  * The Ordering Org CA, `ca_orderer`, is running in container `7b01f5454832`
   181  
   182  These containers all form a [Docker network](https://docs.docker.com/network/)
   183  called `net_test`. You can view the network with the `docker network` command:
   184  
   185  ```
   186  $ docker network inspect net_test
   187  
   188    [
   189        {
   190            "Name": "net_test",
   191            "Id": "f4c9712139311004b8f7acc14e9f90170c5dcfd8cdd06303c7b074624b44dc9f",
   192            "Created": "2020-04-28T22:45:38.525016Z",
   193            "Containers": {
   194                "03373d116c5abf2ca94f6f00df98bb74f89037f511d6490de4a217ed8b6fbcd0": {
   195                    "Name": "orderer.example.com",
   196                    "EndpointID": "0eed871a2aaf9a5dbcf7896aa3c0f53cc61f57b3417d36c56747033fd9f81972",
   197                    "MacAddress": "02:42:c0:a8:70:05",
   198                    "IPv4Address": "192.168.112.5/20",
   199                    "IPv6Address": ""
   200                },
   201                "2438df719f57a597de592cfc76db30013adfdcfa0cec5b375f6b7259f67baff8": {
   202                    "Name": "couchdb1",
   203                    "EndpointID": "52527fb450a7c80ea509cb571d18e2196a95c630d0f41913de8ed5abbd68993d",
   204                    "MacAddress": "02:42:c0:a8:70:06",
   205                    "IPv4Address": "192.168.112.6/20",
   206                    "IPv6Address": ""
   207                },
   208                "6b4d87f65909afd335d7acfe6d79308d6e4b27441b25a829379516e4c7335b88": {
   209                    "Name": "ca_org2",
   210                    "EndpointID": "1cc322a995880d76e1dd1f37ddf9c43f86997156124d4ecbb0eba9f833218407",
   211                    "MacAddress": "02:42:c0:a8:70:04",
   212                    "IPv4Address": "192.168.112.4/20",
   213                    "IPv6Address": ""
   214                },
   215                "77d0fcaee61b8fff43d33331073ab9ce36561a90370b9ef3f77c663c8434e642": {
   216                    "Name": "peer0.org1.example.com",
   217                    "EndpointID": "05d0d34569eee412e28313ba7ee06875a68408257dc47e64c0f4f5ef4a9dc491",
   218                    "MacAddress": "02:42:c0:a8:70:08",
   219                    "IPv4Address": "192.168.112.8/20",
   220                    "IPv6Address": ""
   221                },
   222                "7b01f5454832984fcd9650f05b4affce97319f661710705e6381dfb76cd99fdb": {
   223                    "Name": "ca_orderer",
   224                    "EndpointID": "057390288a424f49d6e9d6f788049b1e18aa28bccd56d860b2be8ceb8173ef74",
   225                    "MacAddress": "02:42:c0:a8:70:02",
   226                    "IPv4Address": "192.168.112.2/20",
   227                    "IPv6Address": ""
   228                },
   229                "7eb5f64bfe5f20701aae8a6660815c4e3a81c3834b71f9e59a62fb99bed1afc7": {
   230                    "Name": "couchdb0",
   231                    "EndpointID": "bfe740be15ec9dab7baf3806964e6b1f0b67032ce1b7ae26ac7844a1b422ddc4",
   232                    "MacAddress": "02:42:c0:a8:70:07",
   233                    "IPv4Address": "192.168.112.7/20",
   234                    "IPv6Address": ""
   235                },
   236                "87aef6062f2324889074cda80fec8fe014d844e10085827f380a91eea4ccdd74": {
   237                    "Name": "ca_org1",
   238                    "EndpointID": "a740090d33ca94dd7c6aaf14a79e1cb35109b549ee291c80195beccc901b16b7",
   239                    "MacAddress": "02:42:c0:a8:70:03",
   240                    "IPv4Address": "192.168.112.3/20",
   241                    "IPv6Address": ""
   242                },
   243                "a86f50ca19079f59552e8674932edd02f7f9af93ded14db3b4c404fd6b1abe9c": {
   244                    "Name": "peer0.org2.example.com",
   245                    "EndpointID": "6e56772b4783b1879a06f86901786fed1c307966b72475ce4631405ba8bca79a",
   246                    "MacAddress": "02:42:c0:a8:70:09",
   247                    "IPv4Address": "192.168.112.9/20",
   248                    "IPv6Address": ""
   249                }
   250            },
   251            "Options": {},
   252            "Labels": {}
   253        }
   254    ]
   255  ```
   256  
   257  See how the eight containers use different IP addresses, while being part of a
   258  single Docker network. (We've abbreviated the output for clarity.)
   259  
   260  Because we are operating the test network as DigiBank and MagnetoCorp,
   261  `peer0.org1.example.com` will belong to the DigiBank organization while
   262  `peer0.org2.example.com` will be operated by MagnetoCorp. Now that the test
   263  network is up and running, we can refer to our network as PaperNet from this point
   264  forward.
   265  
   266  To recap: you've downloaded the Hyperledger Fabric samples repository from
   267  GitHub and you've got a Fabric network running on your local machine. Let's now
   268  start to play the role of MagnetoCorp, who wishes to issue and trade commercial paper.
   269  
   270  ## Monitor the network as MagnetoCorp
   271  
   272  The commercial paper tutorial allows you to act as two organizations by
   273  providing two separate folders for DigiBank and MagnetoCorp. The two folders
   274  contain the smart contracts and application files for each organization. Because
   275  the two organizations have different roles in the trading of the commercial paper,
   276  the application files are different for each organization. Open a new window in
   277  the `fabric-samples` repository and use the following command to change into
   278  the MagnetoCorp directory:
   279  ```
   280  cd commercial-paper/organization/magnetocorp
   281  ```
   282  The first thing we are going to do as MagnetoCorp is monitor the components
   283  of PaperNet. An administrator can view the aggregated output from a set
   284  of Docker containers using the `logspout` [tool](https://github.com/gliderlabs/logspout#logspout).
   285  The tool collects the different output streams into one place, making it easy
   286  to see what's happening from a single window. This can be really helpful for
   287  administrators when installing smart contracts or for developers when invoking
   288  smart contracts, for example.
   289  
   290  In the MagnetoCorp directory, run the following command to run the
   291  `monitordocker.sh`  script and start the `logspout` tool for the containers
   292  associated with PaperNet running on `net_test`:
   293  ```
   294  (magnetocorp admin)$ ./configuration/cli/monitordocker.sh net_test
   295  ...
   296  latest: Pulling from gliderlabs/logspout
   297  4fe2ade4980c: Pull complete
   298  decca452f519: Pull complete
   299  (...)
   300  Starting monitoring on all containers on the network net_test
   301  b7f3586e5d0233de5a454df369b8eadab0613886fc9877529587345fc01a3582
   302  ```
   303  
   304  Note that you can pass a port number to the above command if the default port in `monitordocker.sh` is already in use.
   305  ```
   306  (magnetocorp admin)$ ./monitordocker.sh net_test <port_number>
   307  ```
   308  
   309  This window will now show output from the Docker containers for the remainder of the
   310  tutorial, so go ahead and open another command window. The next thing we will do is
   311  examine the smart contract that MagnetoCorp will use to issue to the commercial
   312  paper.
   313  
   314  ## Examine the commercial paper smart contract
   315  
   316  `issue`, `buy` and `redeem` are the three functions at the heart of the commercial
   317  paper smart contract. It is used by applications to submit transactions which
   318  correspondingly issue, buy and redeem commercial paper on the ledger. Our next
   319  task is to examine this smart contract.
   320  
   321  Open a new terminal in the `fabric-samples` directory and change into the
   322  MagnetoCorp folder to act as the MagnetoCorp developer.
   323  ```
   324  cd commercial-paper/organization/magnetocorp
   325  ```
   326  You can then view the smart contract in the `contract` directory using your chosen
   327  editor (VS Code in this tutorial):
   328  ```
   329  (magnetocorp developer)$ code contract
   330  ```
   331  
   332  In the `lib` directory of the folder, you'll see `papercontract.js` file -- this
   333  contains the commercial paper smart contract!
   334  
   335  ![commercialpaper.vscode1](./commercial_paper.vscode.papercontract.png) *An
   336  example code editor displaying the commercial paper smart contract in `papercontract.js`*
   337  
   338  `papercontract.js` is a JavaScript program designed to run in the Node.js
   339  environment. Note the following key program lines:
   340  
   341  * `const { Contract, Context } = require('fabric-contract-api');`
   342  
   343    This statement brings into scope two key Hyperledger Fabric classes that will
   344    be used extensively by the smart contract  -- `Contract` and `Context`. You
   345    can learn more about these classes in the
   346    [`fabric-shim` JSDOCS](https://hyperledger.github.io/fabric-chaincode-node/).
   347  
   348  
   349  * `class CommercialPaperContract extends Contract {`
   350  
   351    This defines the smart contract class `CommercialPaperContract` based on the
   352    built-in Fabric `Contract` class.  The methods which implement the key
   353    transactions to `issue`, `buy` and `redeem` commercial paper are defined
   354    within this class.
   355  
   356  
   357  * `async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime...) {`
   358  
   359    This method defines the commercial paper `issue` transaction for PaperNet. The
   360    parameters that are passed to this method will be used to create the new
   361    commercial paper.
   362  
   363    Locate and examine the `buy` and `redeem` transactions within the smart
   364    contract.
   365  
   366  
   367  * `let paper = CommercialPaper.createInstance(issuer, paperNumber, issueDateTime...);`
   368  
   369    Within the `issue` transaction, this statement creates a new commercial paper
   370    in memory using the `CommercialPaper` class with the supplied transaction
   371    inputs. Examine the `buy` and `redeem` transactions to see how they similarly
   372    use this class.
   373  
   374  
   375  * `await ctx.paperList.addPaper(paper);`
   376  
   377    This statement adds the new commercial paper to the ledger using
   378    `ctx.paperList`, an instance of a `PaperList` class that was created when the
   379    smart contract context `CommercialPaperContext` was initialized. Again,
   380    examine the `buy` and `redeem` methods to see how they use this class.
   381  
   382  
   383  * `return paper;`
   384  
   385    This statement returns a binary buffer as response from the `issue`
   386    transaction for processing by the caller of the smart contract.
   387  
   388  
   389  Feel free to examine other files in the `contract` directory to understand how
   390  the smart contract works, and read in detail how `papercontract.js` is
   391  designed in the [smart contract processing](../developapps/smartcontract.html)
   392  topic.
   393  
   394  ## Deploy the smart contract to the channel
   395  
   396  Before `papercontract` can be invoked by applications, it must be installed onto
   397  the appropriate peer nodes of the test network and then defined on the channel
   398  using the [Fabric chaincode lifecycle](../chaincode_lifecycle.html#chaincode-lifecycle). The Fabric chaincode
   399  lifecycle allows multiple organizations to agree to the parameters of a chaincode
   400  before the chaincode is deployed to a channel. As a result, we need to install
   401  and approve the chaincode as administrators of both MagnetoCorp and DigiBank.
   402  
   403  ![commercialpaper.install](./commercial_paper.diagram.install.png)  *A MagnetoCorp
   404  administrator installs a copy of the `papercontract` onto a MagnetoCorp peer.*
   405  
   406  Smart contracts are the focus of application development, and are contained
   407  within a Hyperledger Fabric artifact called [chaincode](../chaincode.html). One
   408  or more smart contracts can be defined within a single chaincode, and installing
   409  a chaincode will allow them to be consumed by the different organizations in
   410  PaperNet. It means that only administrators need to worry about chaincode;
   411  everyone else can think in terms of smart contracts.
   412  
   413  ### Install and approve the smart contract as MagnetoCorp
   414  
   415  We will first install and approve the smart contract as the MagnetoCorp admin. Make
   416  sure that you are operating from the `magnetocorp` folder, or navigate back to that
   417  folder using the following command:
   418  ```
   419  cd commercial-paper/organization/magnetocorp
   420  ```
   421  
   422  A MagnetoCorp administrator can interact with PaperNet using the `peer` CLI. However,
   423  the administrator needs to set certain environment variables in their command
   424  window to use the correct set of `peer` binaries, send commands to the address
   425  of the MagnetoCorp peer, and sign requests with the correct cryptographic material.
   426  
   427  You can use a script provided by the sample to set the environment variables in
   428  your command window. Run the following command in the `magnetocorp` directory:
   429  ```
   430  source magnetocorp.sh
   431  ```
   432  
   433  You will see the full list of environment variables printed in your window. We
   434  can now use this command window to interact with PaperNet as the MagnetoCorp
   435  administrator.
   436  
   437  The first step is to install the `papercontract` smart contract. The smart
   438  contract can be packaged into a chaincode using the
   439  `peer lifecycle chaincode package` command. In the MagnetoCorp administrator's
   440  command window, run the following command to create the chaincode package:
   441  ```
   442  (magnetocorp admin)$ peer lifecycle chaincode package cp.tar.gz --lang node --path ./contract --label cp_0
   443  ```
   444  The MagnetoCorp admin can now install the chaincode on the MagnetoCorp peer using
   445  the `peer lifecycle chaincode install` command:
   446  ```
   447  (magnetocorp admin)$ peer lifecycle chaincode install cp.tar.gz
   448  ```
   449  When the chaincode package is installed, you will see messages similar to the following
   450  printed in your terminal:
   451  ```
   452  2020-01-30 18:32:33.762 EST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nEcp_0:ffda93e26b183e231b7e9d5051e1ee7ca47fbf24f00a8376ec54120b1a2a335c\022\004cp_0" >
   453  2020-01-30 18:32:33.762 EST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: cp_0:ffda93e26b183e231b7e9d5051e1ee7ca47fbf24f00a8376ec54120b1a2a335c
   454  ```
   455  Because the MagnetoCorp admin has set `CORE_PEER_ADDRESS=localhost:9051` to
   456  target its commands to `peer0.org2.example.com`, the `INFO 001 Installed remotely...`
   457  indicates that `papercontract` has been successfully installed on this peer.
   458  
   459  After we install the smart contract, we need to approve the chaincode definition
   460  for `papercontract` as MagnetoCorp. The first step is to find the packageID of
   461  the chaincode we installed on our peer. We can query the packageID using the
   462  `peer lifecycle chaincode queryinstalled` command:
   463  ```
   464  peer lifecycle chaincode queryinstalled
   465  ```
   466  
   467  The command will return the same package identifier as the install command. You
   468  should see output similar to the following:
   469  ```
   470  Installed chaincodes on peer:
   471  Package ID: cp_0:ffda93e26b183e231b7e9d5051e1ee7ca47fbf24f00a8376ec54120b1a2a335c, Label: cp_0
   472  ```
   473  
   474  We will need the package ID in the next step, so we will save it as an environment
   475  variable. The package ID may not be the same for all users, so you need to
   476  complete this step using the package ID returned from your command window.
   477  ```
   478  export PACKAGE_ID=cp_0:ffda93e26b183e231b7e9d5051e1ee7ca47fbf24f00a8376ec54120b1a2a335c
   479  ```
   480  
   481  The admin can now approve the chaincode definition for MagnetoCorp using the
   482  `peer lifecycle chaincode approveformyorg` command:
   483  ```
   484  (magnetocorp admin)$ peer lifecycle chaincode approveformyorg --orderer localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name papercontract -v 0 --package-id $PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA
   485  ```
   486  
   487  One of the most important chaincode parameters that channel members need to
   488  agree to using the chaincode definition is the chaincode [endorsement policy](../endorsement-policies.html).
   489  The endorsement policy describes the set of organizations that must endorse
   490  (execute and sign) a transaction before it can be determined to be valid. By
   491  approving the `papercontract` chaincode without the ``--policy`` flag, the
   492  MagnetoCorp admin agrees to using the channel's default `Endorsement` policy,
   493  which in the case of the `mychannel` test channel requires a
   494  majority of organizations on the channel to endorse a transaction. All transactions,
   495  whether valid or invalid, will be recorded on the [ledger blockchain](../ledger/ledger.html#blockchain),
   496  but only valid transactions will update the [world state](../ledger/ledger.html#world-state).
   497  
   498  ### Install and approve the smart contract as DigiBank
   499  
   500  Based on the `mychannel` `LifecycleEndorsement` policy, the Fabric Chaincode lifecycle
   501  will require a majority of organizations on the channel to agree to the chaincode
   502  definition before the chaincode can be committed to the channel.
   503  This implies that we need to approve the `papernet` chaincode as both MagnetoCorp
   504  and DigiBank to get the required majority of 2 out of 2. Open a new terminal
   505  window in the `fabric-samples` and navigate to the folder that contains the
   506  DigiBank smart contract and application files:
   507  ```
   508  (digibank admin)$ cd commercial-paper/organization/digibank/
   509  ```
   510  Use the script in the DigiBank folder to set the environment variables that will
   511  allow you to act as the DigiBank admin:
   512  ```
   513  source digibank.sh
   514  ```
   515  
   516  We can now install and approve `papercontract` as the DigiBank. Run the following
   517  command to package the chaincode:
   518  ```
   519  (digibank admin)$ peer lifecycle chaincode package cp.tar.gz --lang node --path ./contract --label cp_0
   520  ```
   521  The admin can now install the chaincode on the DigiBank peer:
   522  ```
   523  (digibank admin)$ peer lifecycle chaincode install cp.tar.gz
   524  ```
   525  We then need to query and save the packageID of the chaincode that was just
   526  installed:
   527  ```
   528  (digibank admin)$ peer lifecycle chaincode queryinstalled
   529  ```
   530  Save the package ID as an environment variable. Complete this step using the
   531  package ID returned from your console.
   532  ```
   533  export PACKAGE_ID=cp_0:ffda93e26b183e231b7e9d5051e1ee7ca47fbf24f00a8376ec54120b1a2a335c
   534  ```
   535  
   536  The Digibank admin can now approve the chaincode definition of `papercontract`:
   537  ```
   538  (digibank admin)$ peer lifecycle chaincode approveformyorg --orderer localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name papercontract -v 0 --package-id $PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA
   539  ```
   540  
   541  ### Commit the chaincode definition to the channel
   542  
   543  Now that DigiBank and MagnetoCorp have both approved the `papernet` chaincode, we
   544  have the majority we need (2 out of 2) to commit the chaincode definition to the
   545  channel. Once the chaincode is successfully defined on the channel, the
   546  `CommercialPaper` smart contract inside the `papercontract` chaincode can be
   547  invoked by client applications on the channel. Since either organization can
   548  commit the chaincode to the channel, we will continue operating as the
   549  DigiBank admin:
   550  
   551  ![commercialpaper.commit](./commercial_paper.diagram.commit.png)  *After the DigiBank administrator commits the definition of the `papercontract` chaincode to the channel, a new Docker chaincode container will be created to run `papercontract` on both PaperNet peers*
   552  
   553  The DigiBank administrator uses the `peer lifecycle chaincode commit` command
   554  to commit the chaincode definition of `papercontract` to `mychannel`:
   555  ```
   556  (digibank admin)$ peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --peerAddresses localhost:7051 --tlsRootCertFiles ${PEER0_ORG1_CA} --peerAddresses localhost:9051 --tlsRootCertFiles ${PEER0_ORG2_CA} --channelID mychannel --name papercontract -v 0 --sequence 1 --tls --cafile $ORDERER_CA --waitForEvent
   557  ```
   558  The chaincode container will start after the chaincode definition has been
   559  committed to the channel. You can use the `docker ps` command to see
   560  `papercontract` container starting on both peers.
   561  
   562  ```
   563  (digibank admin)$ docker ps
   564  
   565  CONTAINER ID        IMAGE                                                                                                                                                               COMMAND                  CREATED             STATUS              PORTS                                        NAMES
   566  d4ba9dc9c55f        dev-peer0.org1.example.com-cp_0-ebef35e7f1f25eea1dcc6fcad5019477cd7f434c6a5dcaf4e81744e282903535-05cf67c20543ee1c24cf7dfe74abce99785374db15b3bc1de2da372700c25608   "docker-entrypoint.s…"   30 seconds ago      Up 28 seconds                                                    dev-peer0.org1.example.com-cp_0-ebef35e7f1f25eea1dcc6fcad5019477cd7f434c6a5dcaf4e81744e282903535
   567  a944c0f8b6d6        dev-peer0.org2.example.com-cp_0-1487670371e56d107b5e980ce7f66172c89251ab21d484c7f988c02912ddeaec-1a147b6fd2a8bd2ae12db824fad8d08a811c30cc70bc5b6bc49a2cbebc2e71ee   "docker-entrypoint.s…"   31 seconds ago      Up 28 seconds                                                    dev-peer0.org2.example.com-cp_0-1487670371e56d107b5e980ce7f66172c89251ab21d484c7f988c02912ddeaec
   568  ```
   569  
   570  Notice that the containers are named to indicate the peer that started it, and
   571  the fact that it's running `papercontract` version `0`.
   572  
   573  Now that we have deployed the `papercontract` chaincode to the channel, we can
   574  use the MagnetoCorp application to issue the commercial paper. Let's take a
   575  moment to examine the application structure.
   576  
   577  ## Application structure
   578  
   579  The smart contract contained in `papercontract` is called by MagnetoCorp's
   580  application `issue.js`. Isabella uses this application to submit a transaction
   581  to the ledger which issues commercial paper `00001`. Let's quickly examine how
   582  the `issue` application works.
   583  
   584  ![commercialpaper.application](./commercial_paper.diagram.8.png) *A gateway
   585  allows an application to focus on transaction generation, submission and
   586  response. It coordinates transaction proposal, ordering and notification
   587  processing between the different network components.*
   588  
   589  Because the `issue` application submits transactions on behalf of Isabella, it
   590  starts by retrieving Isabella's X.509 certificate from her
   591  [wallet](../developapps/wallet.html), which might be stored on the local file
   592  system or a Hardware Security Module
   593  [HSM](https://en.wikipedia.org/wiki/Hardware_security_module). The `issue`
   594  application is then able to utilize the gateway to submit transactions on the
   595  channel. The Hyperledger Fabric SDK provides a
   596  [gateway](../developapps/gateway.html) abstraction so that applications can
   597  focus on application logic while delegating network interaction to the
   598  gateway. Gateways and wallets make it straightforward to write Hyperledger
   599  Fabric applications.
   600  
   601  So let's examine the `issue` application that Isabella is going to use. Open a
   602  separate terminal window for her, and in `fabric-samples` locate the MagnetoCorp
   603  `/application` folder:
   604  
   605  ```
   606  (isabella)$ cd commercial-paper/organization/magnetocorp/application/
   607  (isabella)$ ls
   608  
   609  addToWallet.js		enrollUser.js		issue.js		package.json
   610  ```
   611  
   612  `addToWallet.js` is the program that Isabella is going to use to load her
   613  identity into her wallet, and `issue.js` will use this identity to create
   614  commercial paper `00001` on behalf of MagnetoCorp by invoking `papercontract`.
   615  
   616  Change to the directory that contains MagnetoCorp's copy of the application
   617  `issue.js`, and use your code editor to examine it:
   618  
   619  ```
   620  (isabella)$ cd commercial-paper/organization/magnetocorp/application
   621  (isabella)$ code issue.js
   622  ```
   623  
   624  Examine this directory; it contains the issue application and all its
   625  dependencies.
   626  
   627  ![commercialpaper.vscode2](./commercial_paper.vscode.issue.png) *A code editor
   628  displaying the contents of the commercial paper application directory.*
   629  
   630  Note the following key program lines in `issue.js`:
   631  
   632  * `const { Wallets, Gateway } = require('fabric-network');`
   633  
   634    This statement brings two key Hyperledger Fabric SDK classes into scope --
   635    `Wallet` and `Gateway`.
   636  
   637  
   638  * `const wallet = await Wallets.newFileSystemWallet('../identity/user/isabella/wallet');`
   639  
   640    This statement identifies that the application will use `isabella` wallet when
   641    it connects to the blockchain network channel. Because Isabella's X.509 certificate
   642    is in the local file system, the application creates a new `FileSystemWallet`. The
   643    application will select a particular identity within `isabella` wallet.
   644  
   645  
   646  * `await gateway.connect(connectionProfile, connectionOptions);`
   647  
   648    This line of code connects to the network using the gateway identified by
   649    `connectionProfile`, using the identity referred to in `ConnectionOptions`.
   650  
   651    See how `../gateway/networkConnection.yaml` and `User1@org1.example.com` are
   652    used for these values respectively.
   653  
   654  
   655  * `const network = await gateway.getNetwork('mychannel');`
   656  
   657    This connects the application to the network channel `mychannel`, where the
   658    `papercontract` was previously deployed.
   659  
   660  
   661  * `const contract = await network.getContract('papercontract');`
   662  
   663    This statement gives the application access to the `papercontract` chaincode.
   664    Once an application has issued getContract, it can submit to any smart contract
   665    transaction implemented within the chaincode.
   666  
   667  * `const issueResponse = await contract.submitTransaction('issue', 'MagnetoCorp', '00001', ...);`
   668  
   669    This line of code submits the a transaction to the network using the `issue`
   670    transaction defined within the smart contract. `MagnetoCorp`, `00001`... are
   671    the values to be used by the `issue` transaction to create a new commercial
   672    paper.
   673  
   674  * `let paper = CommercialPaper.fromBuffer(issueResponse);`
   675  
   676    This statement processes the response from the `issue` transaction. The
   677    response needs to deserialized from a buffer into `paper`, a `CommercialPaper`
   678    object which can interpreted correctly by the application.
   679  
   680  
   681  Feel free to examine other files in the `/application` directory to understand
   682  how `issue.js` works, and read in detail how it is implemented in the
   683  application [topic](../developapps/application.html).
   684  
   685  ## Application dependencies
   686  
   687  The `issue.js` application is written in JavaScript and designed to run in the
   688  Node.js environment that acts as a client to the PaperNet network.
   689  As is common practice, MagnetoCorp's application is built on many
   690  external node packages --- to improve quality and speed of development. Consider
   691  how `issue.js` includes the `js-yaml`
   692  [package](https://www.npmjs.com/package/js-yaml) to process the YAML gateway
   693  connection profile, or the `fabric-network`
   694  [package](https://www.npmjs.com/package/fabric-network) to access the `Gateway`
   695  and `Wallet` classes:
   696  
   697  ```JavaScript
   698  const yaml = require('js-yaml');
   699  const { Wallets, Gateway } = require('fabric-network');
   700  ```
   701  
   702  These packages have to be downloaded from [npm](https://www.npmjs.com/) to the
   703  local file system using the `npm install` command. By convention, packages must
   704  be installed into an application-relative `/node_modules` directory for use at
   705  runtime.
   706  
   707  Open the `package.json` file to see how `issue.js` identifies the packages to
   708  download and their exact versions by examining the "dependencies" section of the file.
   709  
   710  **npm** versioning is very powerful; you can read more about it
   711  [here](https://docs.npmjs.com/getting-started/semantic-versioning).
   712  
   713  Let's install these packages with the `npm install` command -- this may take up
   714  to a minute to complete:
   715  
   716  ```
   717  (isabella)$ cd commercial-paper/organization/magnetocorp/application/
   718  (isabella)$ npm install
   719  
   720  (           ) extract:lodash: sill extract ansi-styles@3.2.1
   721  (...)
   722  added 738 packages in 46.701s
   723  ```
   724  
   725  See how this command has updated the directory:
   726  
   727  ```
   728  (isabella)$ ls
   729  
   730  enrollUser.js 		node_modules	      	package.json
   731  issue.js	      	package-lock.json
   732  ```
   733  
   734  Examine the `node_modules` directory to see the packages that have been
   735  installed. There are lots, because `js-yaml` and `fabric-network` are themselves
   736  built on other npm packages! Helpfully, the `package-lock.json`
   737  [file](https://docs.npmjs.com/files/package-lock.json) identifies the exact
   738  versions installed, which can prove invaluable if you want to exactly reproduce
   739  environments; to test, diagnose problems or deliver proven applications for
   740  example.
   741  
   742  ## Wallet
   743  
   744  Isabella is almost ready to run `issue.js` to issue MagnetoCorp commercial paper
   745  `00001`; there's just one remaining task to perform! As `issue.js` acts on
   746  behalf of Isabella, and therefore MagnetoCorp, it will use identity from her
   747  [wallet](../developapps/wallet.html) that reflects these facts. We now need to
   748  perform this one-time activity of generating the appropriate X.509 credentials
   749  to her wallet.
   750  
   751  The MagnetoCorp Certificate Authority running on PaperNet, `ca_org2`, has an
   752  application user that was registered when the network was deployed. Isabella
   753  can use the identity name and secret to generate the X.509 cryptographic material
   754  for the `issue.js` application. The process of using a CA to generate client side
   755  cryptographic material is referred to as **enrollment**. In a real word scenario,
   756  a network operator would provide the name and secret of a client identity that
   757  was registered with the CA to an application developer. The developer would then
   758  use the credentials to enroll their application and interact with the network.
   759  
   760  The `enrollUser.js` program uses the `fabric-ca-client` class to generate a private
   761  and public key pair, and then issues a **Certificate Signing Request** to the CA.
   762  If the identiy name and secret submitted by Isabella match the credentials
   763  registered with the CA, the CA will issue and sign a certificate that encodes the
   764  public key, establishing that Isabella belongs to MagnetoCorp. When the signing
   765  request is complete, `enrollUser.js` stores the private key and signing certificate
   766  in Isabella's wallet. You can examine the `enrollUser.js` file to learn more about
   767  how the Node SDK uses the `fabric-ca-client` class to complete these tasks.
   768  
   769  In Isabella's terminal window, run the `enrollUser.js` program to add identity
   770  information to her wallet:
   771  
   772  ```
   773  (isabella)$ node enrollUser.js
   774  
   775  Wallet path: /Users/nikhilgupta/fabric-samples/commercial-paper/organization/magnetocorp/identity/user/isabella/wallet
   776  Successfully enrolled client user "isabella" and imported it into the wallet
   777  ```
   778  
   779  We can now turn our focus to the result of this program --- the contents of the
   780  wallet which will be used to submit transactions to PaperNet:
   781  
   782  ```
   783  (isabella)$ ls ../identity/user/isabella/wallet/
   784  
   785  isabella.id
   786  ```
   787  
   788  Isabella can store multiple identities in her wallet, though in our example, she
   789  only uses one. The `wallet` folder contains an `isabella.id` file that provides
   790  the information that Isabella needs to connect to the network. Other identities
   791  used by Isabella would have their own file. You can open this file to see the
   792  identity information that `issue.js` will use on behalf of Isabella inside a JSON
   793  file. The output has been formatted for clarity.
   794  ```
   795  (isabella)$  cat ../identity/user/isabella/wallet/*
   796  
   797  {
   798    "credentials": {
   799      "certificate": "-----BEGIN CERTIFICATE-----\nMIICKTCCAdCgAwIBAgIQWKwvLG+sqeO3LwwQK6avZDAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMi5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMi5leGFtcGxlLmNvbTAeFw0yMDAyMDQxOTA5MDBaFw0zMDAyMDExOTA5MDBa\nMGwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMQ8wDQYDVQQLEwZjbGllbnQxHzAdBgNVBAMMFlVzZXIxQG9y\nZzIuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT4TnTblx0k\ngfqX+NN7F76Me33VTq3K2NUWZRreoJzq6bAuvdDR+iFvVPKXbdORnVvRSATcXsYl\nt20yU7n/53dbo00wSzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADArBgNV\nHSMEJDAigCDOCdm4irsZFU3D6Hak4+84QRg1N43iwg8w1V6DRhgLyDAKBggqhkjO\nPQQDAgNHADBEAiBhzKix1KJcbUy9ey5ulWHRUMbqdVCNHe/mRtUdaJagIgIgYpbZ\nXf0CSiTXIWOJIsswN4Jp+ZxkJfFVmXndqKqz+VM=\n-----END CERTIFICATE-----\n",
   800      "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQggs55vQg2oXi8gNi8\nNidE8Fy5zenohArDq3FGJD8cKU2hRANCAAT4TnTblx0kgfqX+NN7F76Me33VTq3K\n2NUWZRreoJzq6bAuvdDR+iFvVPKXbdORnVvRSATcXsYlt20yU7n/53db\n-----END PRIVATE KEY-----\n"
   801    },
   802    "mspId": "Org2MSP",
   803    "type": "X.509",
   804    "version": 1
   805  }
   806  ```
   807  
   808  In the file you can notice the following:
   809  
   810  * a `"privateKey":` used to sign transactions on Isabella's behalf, but not
   811    distributed outside of her immediate control.
   812  
   813  * a `"certificate":` which contains Isabella's public key and other X.509
   814    attributes added by the Certificate Authority at certificate creation. This
   815    certificate is distributed to the network so that different actors at different
   816    times can cryptographically verify information created by Isabella's private key.
   817  
   818  You can Learn more about certificates [here](../identity/identity.html#digital-certificates). In practice, the
   819  certificate file also contains some Fabric-specific metadata such as
   820  Isabella's organization and role -- read more in the [wallet](../developapps/wallet.html) topic.
   821  
   822  ## Issue application
   823  
   824  Isabella can now use `issue.js` to submit a transaction that will issue
   825  MagnetoCorp commercial paper `00001`:
   826  
   827  ```
   828  (isabella)$ node issue.js
   829  
   830  Connect to Fabric gateway.
   831  Use network channel: mychannel.
   832  Use org.papernet.commercialpaper smart contract.
   833  Submit commercial paper issue transaction.
   834  Process issue transaction response.{"class":"org.papernet.commercialpaper","key":"\"MagnetoCorp\":\"00001\"","currentState":1,"issuer":"MagnetoCorp","paperNumber":"00001","issueDateTime":"2020-05-31","maturityDateTime":"2020-11-30","faceValue":"5000000","owner":"MagnetoCorp"}
   835  MagnetoCorp commercial paper : 00001 successfully issued for value 5000000
   836  Transaction complete.
   837  Disconnect from Fabric gateway.
   838  Issue program complete.
   839  ```
   840  
   841  The `node` command initializes a Node.js environment, and runs `issue.js`. We
   842  can see from the program output that MagnetoCorp commercial paper 00001 was
   843  issued with a face value of 5M USD.
   844  
   845  As you've seen, to achieve this, the application invokes the `issue` transaction
   846  defined in the `CommercialPaper` smart contract within `papercontract.js`.
   847  The smart contract interacts with the ledger via the
   848  Fabric APIs, most notably `putState()` and `getState()`, to represent the new
   849  commercial paper as a vector state within the world state. We'll see how this
   850  vector state is subsequently manipulated by the `buy` and `redeem` transactions
   851  also defined within the smart contract.
   852  
   853  All the time, the underlying Fabric SDK handles the transaction endorsement,
   854  ordering and notification process, making the application's logic
   855  straightforward; the SDK uses a [gateway](../developapps/gateway.html) to
   856  abstract away network details and
   857  [connectionOptions](../developapps/connectoptions.html) to declare more advanced
   858  processing strategies such as transaction retry.
   859  
   860  Let's now follow the lifecycle of MagnetoCorp 00001 by switching our emphasis
   861  to an employee of DigiBank, Balaji, who will buy the commercial paper using a
   862  DigiBank application.
   863  
   864  ## Digibank applications
   865  
   866  Balaji uses DigiBank's `buy` application to submit a transaction to the ledger
   867  which transfers ownership of commercial paper `00001` from MagnetoCorp to
   868  DigiBank. The `CommercialPaper` smart contract is the same as that used by
   869  MagnetoCorp's application, however the transaction is different this time --
   870  it's `buy` rather than `issue`. Let's examine how DigiBank's application works.
   871  
   872  Open a separate terminal window for Balaji. In `fabric-samples`, change to the
   873  DigiBank application directory that contains the application, `buy.js`, and open
   874  it with your editor:
   875  
   876  ```
   877  (balaji)$ cd commercial-paper/organization/digibank/application/
   878  (balaji)$ code buy.js
   879  ```
   880  
   881  As you can see, this directory contains both the `buy` and `redeem` applications
   882  that will be used by Balaji.
   883  
   884  
   885  ![commercialpaper.vscode3](./commercial_paper.diagram.12.png) *DigiBank's
   886  commercial paper directory containing the `buy.js` and `redeem.js`
   887  applications.*
   888  
   889  DigiBank's `buy.js` application is very similar in structure to MagnetoCorp's
   890  `issue.js` with two important differences:
   891  
   892  
   893    * **Identity**: the user is a DigiBank user `Balaji` rather than MagnetoCorp's
   894      `Isabella`
   895  
   896      ```JavaScript
   897      const wallet = await Wallets.newFileSystemWallet('../identity/user/balaji/wallet');
   898      ```
   899  
   900      See how the application uses the `balaji` wallet when it connects to the
   901      PaperNet network channel. `buy.js` selects a particular identity within
   902      `balaji` wallet.
   903  
   904  
   905    * **Transaction**: the invoked transaction is `buy` rather than `issue`
   906  
   907      ```JavaScript
   908      const buyResponse = await contract.submitTransaction('buy', 'MagnetoCorp', '00001', ...);
   909      ```
   910  
   911      A `buy` transaction is submitted with the values `MagnetoCorp`, `00001`, ...,
   912      that are used by the `CommercialPaper` smart contract class to transfer
   913      ownership of commercial paper `00001` to DigiBank.
   914  
   915  Feel free to examine other files in the `application` directory to understand
   916  how the application works, and read in detail how `buy.js` is implemented in
   917  the application [topic](../developapps/application.html).
   918  
   919  ## Run as DigiBank
   920  
   921  The DigiBank applications which buy and redeem commercial paper have a very
   922  similar structure to MagnetoCorp's issue application. Therefore, let’s install
   923  their dependencies and set up Balaji's wallet so that he can use these
   924  applications to buy and redeem commercial paper.
   925  
   926  Like MagnetoCorp, Digibank must the install the required application packages
   927  using the ``npm install`` command, and again, this make take a short time to
   928  complete.
   929  
   930  In the DigiBank administrator window, install the application dependencies:
   931  
   932  ```
   933  (digibank admin)$ cd commercial-paper/organization/digibank/application/
   934  (digibank admin)$ npm install
   935  
   936  (            ) extract:lodash: sill extract ansi-styles@3.2.1
   937  (...)
   938  added 738 packages in 46.701s
   939  ```
   940  
   941  In Balaji's command window, run the `enrollUser.js` program to generate a
   942  certificate and private key and them to his wallet:
   943  ```
   944  (balaji)$ node enrollUser.js
   945  
   946  Wallet path: /Users/nikhilgupta/fabric-samples/commercial-paper/organization/digibank/identity/user/balaji/wallet
   947  Successfully enrolled client user "balaji" and imported it into the wallet
   948  ```
   949  
   950  The `addToWallet.js` program has added identity information for `balaji`, to his
   951  wallet, which will be used by `buy.js` and `redeem.js` to submit transactions to
   952  `PaperNet`.
   953  
   954  Like Isabella, Balaji can store multiple identities in his wallet, though in our
   955  example, he only uses one. His corresponding id file at
   956  `digibank/identity/user/balaji/wallet/balaji.id` is very similar Isabella's ---
   957  feel free to examine it.
   958  
   959  ## Buy application
   960  
   961  Balaji can now use `buy.js` to submit a transaction that will transfer ownership
   962  of MagnetoCorp commercial paper 00001 to DigiBank.
   963  
   964  Run the `buy` application in Balaji's window:
   965  
   966  ```
   967  (balaji)$ node buy.js
   968  
   969  Connect to Fabric gateway.
   970  Use network channel: mychannel.
   971  Use org.papernet.commercialpaper smart contract.
   972  Submit commercial paper buy transaction.
   973  Process buy transaction response.
   974  MagnetoCorp commercial paper : 00001 successfully purchased by DigiBank
   975  Transaction complete.
   976  Disconnect from Fabric gateway.
   977  Buy program complete.
   978  ```
   979  
   980  You can see the program output that MagnetoCorp commercial paper 00001 was
   981  successfully purchased by Balaji on behalf of DigiBank. `buy.js` invoked the
   982  `buy` transaction defined in the `CommercialPaper` smart contract which updated
   983  commercial paper `00001` within the world state using the `putState()` and
   984  `getState()` Fabric APIs. As you've seen, the application logic to buy and issue
   985  commercial paper is very similar, as is the smart contract logic.
   986  
   987  ## Redeem application
   988  
   989  The final transaction in the lifecycle of commercial paper 00001 is for
   990  DigiBank to redeem it with MagnetoCorp. Balaji uses `redeem.js` to submit a
   991  transaction to perform the redeem logic within the smart contract.
   992  
   993  Run the `redeem` transaction in Balaji's window:
   994  
   995  ```
   996  (balaji)$ node redeem.js
   997  
   998  Connect to Fabric gateway.
   999  Use network channel: mychannel.
  1000  Use org.papernet.commercialpaper smart contract.
  1001  Submit commercial paper redeem transaction.
  1002  Process redeem transaction response.
  1003  MagnetoCorp commercial paper : 00001 successfully redeemed with MagnetoCorp
  1004  Transaction complete.
  1005  Disconnect from Fabric gateway.
  1006  Redeem program complete.
  1007  ```
  1008  
  1009  Again, see how the commercial paper 00001 was successfully redeemed when
  1010  `redeem.js` invoked the `redeem` transaction defined in `CommercialPaper`.
  1011  Again, it updated commercial paper `00001` within the world state to reflect
  1012  that the ownership returned to MagnetoCorp, the issuer of the paper.
  1013  
  1014  ## Clean up
  1015  
  1016  When you are finished using the Commercial Paper tutorial, you can use a script
  1017  to clean up your environment. Use a command window to navigate back to the root
  1018  directory of the commercial paper sample:
  1019  ```
  1020  cd fabric-samples/commercial-paper
  1021  ```
  1022  You can then bring down the network with the following command:
  1023  ```
  1024  ./network-clean.sh
  1025  ```
  1026  This command will bring down the peers, CouchDB containers, and ordering node of the network, in addition to the logspout tool. It will also remove the identities that we created for Isabella and Balaji. Note that all of the data on the ledger will be lost. If you want to go through the tutorial again, you will start from a clean initial state.
  1027  
  1028  ## Further reading
  1029  
  1030  To understand how applications and smart contracts shown in this tutorial work
  1031  in more detail, you'll find it helpful to read
  1032  [Developing Applications](../developapps/developing_applications.html). This
  1033  topic will give you a fuller explanation of the commercial paper scenario, the
  1034  PaperNet business network, its actors, and how the applications and smart
  1035  contracts they use work in detail.
  1036  
  1037  Also feel free to use this sample to start creating your own applications and
  1038  smart contracts!
  1039  
  1040  <!--- Licensed under Creative Commons Attribution 4.0 International License
  1041  https://creativecommons.org/licenses/by/4.0/ -->