github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/docs/source/write_first_app.rst (about)

     1  Writing Your First Application
     2  ==============================
     3  
     4  .. note:: If you're not yet familiar with the fundamental architecture of a
     5            Fabric network, you may want to visit the :doc:`blockchain` and
     6            :doc:`build_network` documentation prior to continuing.
     7  
     8  In this section we'll be looking at two sample applications to see how Fabric
     9  apps work. These apps (and the smart contract they use) -- collectively known as
    10  "Fabcar" -- involve querying a ledger that has been pre-populated with cars and
    11  then updating that ledger to add new cars and to change car owners.
    12  
    13  We’ll go through three principle steps:
    14  
    15    **1. Setting up a development environment.** Our application needs a network to
    16    interact with, so we'll download one stripped down to just the components we need
    17    to run queries and updates:
    18  
    19    .. image:: images/AppConceptsOverview.png
    20  
    21    **2. Learning the parameters of the sample smart contract our app will use.** Our
    22    smart contract contains various functions that allow us to interact with the ledger
    23    in different ways. We’ll go in and inspect that smart contract to learn about the
    24    functions our applications will be using.
    25  
    26    **3. Developing the applications to be able to query and update Fabric records.**
    27    We'll get into the app code itself (our apps have been written in Javascript) and
    28    manually manipulate the variables to run different kinds of queries and updates.
    29  
    30  After completing this tutorial you should have a basic understanding of how
    31  an application is programmed in conjunction with a smart contract to interact
    32  with the ledger on a Fabric network. All in about 30 minutes.
    33  
    34  First, let's get our network and our apps...
    35  
    36  Setting up a Development Environment
    37  ------------------------------------
    38  
    39  Visit the :doc:`prereqs` page and ensure you have the necessary dependencies
    40  installed on your machine.
    41  
    42  Also, let's remove any containers and chaincode (smart contracts run on
    43  chaincode) images you might have running to ensure you don't have a port
    44  conflict or Docker issue.
    45  
    46  First, remove the containers:
    47  
    48  .. code:: bash
    49  
    50    docker rm -f $(docker ps -aq)
    51  
    52  Next, delete the chaincode image:
    53  
    54  .. code:: bash
    55  
    56    docker rmi dev-peer0.org1.example.com-fabcar-1.0
    57  
    58  Now that your machine is set up, navigate to a directory where you want the
    59  samples downloaded to and issue the clone command:
    60  
    61  .. code:: bash
    62  
    63    git clone https://github.com/hyperledger/fabric-samples.git
    64  
    65  This command will create a directory, ``fabric-samples`` (in which multiple
    66  samples and tutorial apps have now been downloaded), and a specific
    67  subdirectory, ``fabcar``.
    68  
    69  Enter that directory:
    70  
    71  .. code:: bash
    72  
    73    cd fabric-samples/fabcar
    74  
    75  Now take a look at what's inside your ``fabcar`` directory.
    76  
    77  .. code:: bash
    78  
    79    ls
    80  
    81  You should see the following:
    82  
    83  .. code:: bash
    84  
    85     creds invoke.js package.json query.js startFabric.sh
    86  
    87  Use the ``startFabric.sh`` script to launch the network. This script downloads
    88  and extracts the Fabric docker images, so it will take a few minutes to
    89  complete:
    90  
    91  .. code:: bash
    92  
    93    ./startFabric.sh
    94  
    95  One last thing. We need to install the SDK (software development kit) node
    96  modules:
    97  
    98  .. code:: bash
    99  
   100    npm install
   101  
   102  Alright, now that you’ve got a sample network and some code, let’s take a
   103  look at how the different pieces fit together.
   104  
   105  How Applications Interact with the Network
   106  ------------------------------------------
   107  
   108  For a more in-depth look at the components in our Fabcar network (and how
   109  they're deployed) as well as how applications interact with those components
   110  on more of a granular level, click :doc:`understand_fabcar_network`.
   111  
   112  Developers more interested in seeing what applications **do** -- as well as
   113  looking at the code itself to see how an application is constructed -- should
   114  continue. For now, the most important thing to know is that applications use
   115  a software development kit (SDK) to access the **APIs** that permit queries and
   116  updates to the ledger.
   117  
   118  Querying the Ledger
   119  -------------------
   120  
   121  Queries are how you read data from the ledger. This data is stored as a series
   122  of key/value pairs, and you can query for the value of a single key, multiple
   123  keys, or -- if the ledger is written in a rich data storage format like JSON --
   124  perform complex searches against it (looking for all assets that contain
   125  certain keywords, for example).
   126  
   127  This is a representation of how a query works:
   128  
   129  .. image:: images/QueryingtheLedger.png
   130  
   131  .. note:: You will issue all subsequent commands from the ``fabcar`` directory.
   132  
   133  First, let's run our ``query.js`` program to return a listing of all the cars on
   134  the ledger. A function that will query all the cars, ``queryAllCars``, is
   135  pre-loaded in the app, so we can simply run the program as is:
   136  
   137  .. code:: bash
   138  
   139    node query.js
   140  
   141  It should return something like this:
   142  
   143  .. code:: json
   144  
   145    Query result count =  1
   146    Response is  [{"Key":"CAR0", "Record":{"colour":"blue","make":"Toyota","model":"Prius","owner":"Tomoko"}},
   147    {"Key":"CAR1",   "Record":{"colour":"red","make":"Ford","model":"Mustang","owner":"Brad"}},
   148    {"Key":"CAR2", "Record":{"colour":"green","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}},
   149    {"Key":"CAR3", "Record":{"colour":"yellow","make":"Volkswagen","model":"Passat","owner":"Max"}},
   150    {"Key":"CAR4", "Record":{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}},
   151    {"Key":"CAR5", "Record":{"colour":"purple","make":"Peugeot","model":"205","owner":"Michel"}},
   152    {"Key":"CAR6", "Record":{"colour":"white","make":"Chery","model":"S22L","owner":"Aarav"}},
   153    {"Key":"CAR7", "Record":{"colour":"violet","make":"Fiat","model":"Punto","owner":"Pari"}},
   154    {"Key":"CAR8", "Record":{"colour":"indigo","make":"Tata","model":"Nano","owner":"Valeria"}},
   155    {"Key":"CAR9", "Record":{"colour":"brown","make":"Holden","model":"Barina","owner":"Shotaro"}}]
   156  
   157  These are the 10 cars. A black Tesla Model S owned by Adriana, a red Ford Mustang
   158  owned by Brad, a violet Fiat Punto owned by Pari, and so on. The ledger is
   159  key/value based and in our implementation the key is ``CAR0`` through ``CAR9``.
   160  This will become particularly important in a moment.
   161  
   162  Now let's see what it looks like under the hood (if you'll forgive the pun).
   163  Use an editor (e.g. atom or visual studio) and open the ``query.js`` program.
   164  
   165  The initial section of the application defines certain variables such as
   166  chaincode ID, channel name and network endpoints. In our sample app, these
   167  variables have been baked-in, but in a real app these variables would have to
   168  be specified by the app dev.
   169  
   170  .. code:: bash
   171  
   172    var options = {
   173        wallet_path: path.join(__dirname, './network/creds'),
   174        user_id: 'PeerAdmin',
   175        channel_id: 'mychannel',
   176        chaincode_id: 'fabcar',
   177        network_url: 'grpc://localhost:7051',
   178    };
   179  
   180  This is the chunk where we construct our query:
   181  
   182  .. code:: bash
   183  
   184       // queryCar - requires 1 argument, ex: args: ['CAR4'],
   185       // queryAllCars - requires no arguments , ex: args: [''],
   186       const request = {
   187             chaincodeId: options.chaincode_id,
   188             txId: transaction_id,
   189             fcn: 'queryAllCars',
   190             args: ['']
   191       };
   192  
   193  When the application ran, it invoked the fabcar smart contract, ran the
   194  ``queryAllCars`` function within it, and passed no arguments to it.
   195  
   196  To take a look at the available functions within our smart contract, navigate
   197  to the ``chaincode`` subdirectory and open ``fabcar.go`` in your editor. You'll
   198  see that we have the following functions available to call: ``initLedger``,
   199  ``queryCar``, ``queryAllCars``, ``createCar``, and ``changeCarOwner``.
   200  
   201  Let's take a closer look at the ``queryAllCars`` function to see how it
   202  interacts with the ledger.
   203  
   204  .. code:: bash
   205  
   206     func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response {
   207  
   208  	startKey := "CAR0"
   209  	endKey := "CAR999"
   210  
   211  	resultsIterator, err := APIstub.GetStateByRange(startKey, endKey)
   212  
   213  This defines the range of ``queryAllCars``. Every car between ``CAR0`` and
   214  ``CAR999`` -- 1,000 cars in all, assuming every call has been tagged properly
   215  -- will be returned by the query.
   216  
   217  Below is a representation of how an app would call different functions in
   218  chaincode, showing the various APIs -- ``createCar``, ``queryallCars``, etc --
   219  available to use.
   220  
   221  .. image:: images/RunningtheSample.png
   222  
   223  We can see our ``queryAllCars`` function, as well as one called ``createCar``,
   224  that will allow us to update the ledger and ultimately append a new block to
   225  the chain in a moment.
   226  
   227  But first, go back to the ``query.js`` program and edit the constructor request
   228  to query ``CAR4``. We do this by changing the function in ``query.js`` from
   229  ``queryAllCars`` to ``queryCar`` and passing ``CAR4`` as the specific
   230  “argument” (or “key”).
   231  
   232  ``query.js`` should now look like this:
   233  
   234  .. code:: bash
   235  
   236    const request = {
   237          chaincodeId: options.chaincode_id,
   238          txId: transaction_id,
   239          fcn: 'queryCar',
   240          args: ['CAR4']
   241    };
   242  
   243  Save the program and navigate back to your ``fabcar`` directory.  Now run the
   244  program again:
   245  
   246  .. code:: bash
   247  
   248    node query.js
   249  
   250  You should see the following:
   251  
   252  .. code:: json
   253  
   254    {"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}
   255  
   256  If you go back and look at the result from when we queried every car before,
   257  you can see that CAR4 was Adriana’s black Tesla model S, which is the result
   258  that was returned here.
   259  
   260  Using the ``queryCar`` function, we can query against any key (e.g. ``CAR0``)
   261  and get whatever make, model, color, and owner correspond to that car.
   262  
   263  Great. At this point you should be comfortable with the basic query functions
   264  in the smart contract and the handful of parameters in the query program.
   265  Time to update the ledger...
   266  
   267  Updating the Ledger
   268  -------------------
   269  
   270  Now that we’ve done a few ledger queries and added a bit of code, we’re ready to
   271  update the ledger. There are a lot of potential updates we could make, but
   272  let's start by creating a car.
   273  
   274  Below we can see how this process works. An update is proposed, endorsed,
   275  then returned to the application, which sends it to be ordered and written
   276  to the ledger:
   277  
   278  .. image:: images/UpdatingtheLedger.png
   279  
   280  Our first update to the ledger will be to create a new car.  We have a separate
   281  Javascript program -- ``invoke.js`` -- that we will use to make updates. Just
   282  as with queries, use an editor to open the program and navigate to the
   283  codeblock where we construct our invocation:
   284  
   285  .. code:: bash
   286  
   287      // createCar - requires 5 args, ex: args: ['CAR11', 'Honda', 'Accord', 'Black', 'Tom'],
   288      // changeCarOwner - requires 2 args , ex: args: ['CAR10', 'Barry'],
   289      // send proposal to endorser
   290      var request = {
   291          targets: targets,
   292          chaincodeId: options.chaincode_id,
   293          fcn: '',
   294          args: [''],
   295          chainId: options.channel_id,
   296          txId: tx_id
   297      };
   298  
   299  You'll see that we can call one of two functions - ``createCar`` or
   300  ``changeCarOwner``. First, let’s create a red Chevy Volt and give it to an
   301  owner named Nick. We're up to ``CAR9`` on our ledger, so we'll use ``CAR10``
   302  as the identifying key here. Edit this codeblock to look like this:
   303  
   304  .. code:: bash
   305  
   306      var request = {
   307          targets: targets,
   308          chaincodeId: options.chaincode_id,
   309          fcn: 'createCar',
   310          args: ['CAR10', 'Chevy', 'Volt', 'Red', 'Nick'],
   311          chainId: options.channel_id,
   312          txId: tx_id
   313      };
   314  
   315  Save it and run the program:
   316  
   317  .. code:: bash
   318  
   319     node invoke.js
   320  
   321  There will be some output in the terminal about Proposal Response and
   322  Transaction ID. However, all we're concerned with is this message:
   323  
   324  .. code:: bash
   325  
   326     The transaction has been committed on peer localhost:7053
   327  
   328  To see that this transaction has been written, go back to ``query.js`` and
   329  change the argument from ``CAR4`` to ``CAR10``.
   330  
   331  In other words, change this:
   332  
   333    const request = {
   334          chaincodeId: options.chaincode_id,
   335          txId: transaction_id,
   336          fcn: 'queryCar',
   337          args: ['CAR4']
   338    };
   339  
   340  To this:
   341  
   342  .. code:: bash
   343  
   344    const request = {
   345          chaincodeId: options.chaincode_id,
   346          txId: transaction_id,
   347          fcn: 'queryCar',
   348          args: ['CAR10']
   349    };
   350  
   351  Save once again, then query:
   352  
   353  .. code:: bash
   354  
   355    node query.js
   356  
   357  Which should return this:
   358  
   359  .. code:: bash
   360  
   361     Response is  {"colour":"Red","make":"Chevy","model":"Volt","owner":"Nick"}
   362  
   363  Congratulations. You’ve created a car!
   364  
   365  So now that we’ve done that, let’s say that Nick is feeling generous and he
   366  wants to give his Chevy Volt to someone named Barry.
   367  
   368  To do this go back to ``invoke.js`` and change the function from ``createCar``
   369  to ``changeCarOwner`` and input the arguments like this:
   370  
   371  .. code:: bash
   372  
   373       var request = {
   374           targets: targets,
   375           chaincodeId: options.chaincode_id,
   376           fcn: 'changeCarOwner',
   377           args: ['CAR10', 'Barry'],
   378           chainId: options.channel_id,
   379           txId: tx_id
   380       };
   381  
   382  The first argument -- ``CAR10`` -- reflects the car that will be changing
   383  owners. The second argument -- ``Barry`` -- defines the new owner of the car.
   384  
   385  Save and execute the program again:
   386  
   387  .. code:: bash
   388  
   389    node invoke.js
   390  
   391  Now let’s query the ledger and see that it’s been updated to reflect this:
   392  
   393  .. code:: bash
   394  
   395    node query.js
   396  
   397  It should return this result:
   398  
   399  .. code:: bash
   400  
   401     Response is  {"colour":"Red","make":"Chevy","model":"Volt","owner":"Barry"}
   402  
   403  The ownership of ``CAR10`` has been changed from Nick to Barry.
   404  
   405  Summary
   406  -------
   407  
   408  Now that we’ve done a few queries and a few updates, you should have a pretty
   409  good sense of how applications interact with the network. You’ve seen the basics
   410  of the roles smart contracts, APIs, and the SDK play in queries and updates and
   411  you should have a feel for how different kinds of applications could be used to
   412  perform other business tasks and operations.
   413  
   414  In subsequent documents we’ll learn how to actually **write** a smart contract
   415  and how some of these more low level application functions can be leveraged
   416  (especially relating to identity and membership services).
   417  
   418  Additional Resources
   419  --------------------
   420  
   421  The `Hyperledger Fabric Node SDK repo <https://github.com/hyperledger/fabric-sdk-node>`__
   422  is an excellent resource for deeper documentation and sample code.  You can also consult
   423  the Fabric community and component experts on `Hyperledger Rocket Chat <https://chat.hyperledger.org/home>`__.
   424  
   425  .. Licensed under Creative Commons Attribution 4.0 International License
   426     https://creativecommons.org/licenses/by/4.0/