github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/docs/source/write_first_app.rst (about) 1 Writing Your First Application 2 ============================== 3 4 The goal of this document is to show the tasks and provide a baseline for writing 5 your first application against a Hyperledger Fabric network. 6 7 At the most basic level, applications on a blockchain network are what enable 8 users to **query** a ledger (asking for specific records it contains), or to 9 **update** it (adding records to it). 10 11 Our application, composed in Javascript, leverages the Node.js SDK to interact 12 with the network (where our ledger exists). This tutorial will guide you through 13 the three steps involved in writing your first application. 14 15 **1. Starting a test Hyperledger Fabric blockchain network.** We need some basic components 16 in our network in order to query and update the ledger. These components -- 17 a peer node, ordering node and Certificate Authority -- serve as the backbone of 18 our network; we'll also have a CLI container used for a few administrative commands. 19 A single script will download and launch this test network. 20 21 **2. Learning the parameters of the sample smart contract our app will use.** Our 22 smart contracts contain various functions that allow us to interact with the ledger 23 in different ways. For example, we can read data holistically or on a more granular 24 level. 25 26 **3. Developing the application to be able to query and update records.** 27 We provide two sample applications -- one for querying the ledger and another for 28 updating it. Our apps will use the SDK APIs to interact with the network and 29 ultimately call these functions. 30 31 After completing this tutorial, you should have a basic understanding of how 32 an application, using the Hyperledger Fabric SDK for Node.js, is programmed 33 in conjunction with a smart contract to interact with the ledger on a 34 Hyperledger Fabric network. 35 36 First, let's launch our test network... 37 38 Getting a Test Network 39 ---------------------- 40 41 Visit the :doc:`prereqs` page and ensure you have the necessary dependencies installed 42 on your machine. 43 44 Now determine a working directory where you want to clone the fabric-samples repo. Issue 45 the clone command and change into the ``fabcar`` subdirectory 46 47 .. code:: bash 48 49 git clone https://github.com/hyperledger/fabric-samples.git 50 cd fabric-samples/fabcar 51 52 This subdirectory -- ``fabcar`` -- contains the scripts 53 and application code to run the sample app. Issue an ``ls`` from 54 this directory. You should see the following: 55 56 .. code:: bash 57 58 chaincode invoke.js network package.json query.js startFabric.sh 59 60 Now use the ``startFabric.sh`` script to launch the network. 61 62 .. note:: The following command downloads and extracts the Hyperledger Fabric 63 Docker images, so it will take a few minutes to complete. 64 65 .. code:: bash 66 67 ./startFabric.sh 68 69 For the sake of brevity, we won't delve into the details of what's happening with 70 this command. Here's a quick synopsis: 71 72 * launches a peer node, ordering node, Certificate Authority and CLI container 73 * creates a channel and joins the peer to the channel 74 * installs smart contract (i.e. chaincode) onto the peer's file system and instantiates said chaincode on the channel; instantiate starts a chaincode container 75 * calls the ``initLedger`` function to populate the channel ledger with 10 unique cars 76 77 .. note:: These operations will typically be done by an organizational or peer admin. The script uses the 78 CLI to execute these commands, however there is support in the SDK as well. 79 Refer to the `Hyperledger Fabric Node SDK repo <https://github.com/hyperledger/fabric-sdk-node>`__ 80 for example scripts. 81 82 Issue a ``docker ps`` command to reveal the processes started by the ``startFabric.sh`` script. 83 You can learn more about the details and mechanics of these operations in the 84 :doc:`build_network` section. Here we'll just focus on the application. The following picture 85 provides a simplistic representation of how the application interacts with the 86 Hyperledger Fabric network. 87 88 .. image:: images/AppConceptsOverview.png 89 90 Alright, now that you’ve got a sample network and some code, let’s take a 91 look at how the different pieces fit together. 92 93 How Applications Interact with the Network 94 ------------------------------------------ 95 96 Applications use **APIs** to invoke smart contracts (referred to as "chaincode"). 97 These smart contracts are hosted in the network and identified by name and version. 98 For example, our chaincode container is titled - ``dev-peer0.org1.example.com-fabcar-1.0`` - where 99 the name is ``fabcar``, the version is ``1.0`` and the peer it is running against is ``dev-peer0.org1.example.com``. 100 101 APIs are accessible with a software development kit (SDK). For purposes of this 102 exercise, we'll be using the `Hyperledger Fabric Node SDK 103 <https://fabric-sdk-node.github.io/>`__ though there is also a Java SDK and 104 CLI that can be used to develop applications. 105 106 Querying the Ledger 107 ------------------- 108 Queries are how you read data from the ledger. You can query for the value 109 of a single key, multiple keys, or -- if the ledger is written in a rich data storage 110 format like JSON -- perform complex searches against it (looking for all 111 assets that contain certain keywords, for example). 112 113 .. image:: images/QueryingtheLedger.png 114 115 As we said earlier, our sample network has an active chaincode container and 116 a ledger that has been primed with 10 different cars. We also have some 117 sample Javascript code - ``query.js`` - in the ``fabcar`` directory that 118 can be used to query the ledger for details on the cars. 119 120 Before we take a look at how that app works, we need to install the SDK node 121 modules in order for our program to function. From your ``fabcar`` directory, 122 issue the following: 123 124 .. code:: bash 125 126 npm install 127 128 .. note:: You will issue all subsequent commands from the ``fabcar`` directory. 129 130 Now we can run our javascript programs. First, let's run our ``query.js`` 131 program to return a listing of all the cars on the ledger. A function that 132 will query all the cars, ``queryAllCars``, is pre-loaded in the app, 133 so we can simply run the program as is: 134 135 .. code:: bash 136 137 node query.js 138 139 It should return something like this: 140 141 .. code:: json 142 143 Query result count = 1 144 Response is [{"Key":"CAR0", "Record":{"colour":"blue","make":"Toyota","model":"Prius","owner":"Tomoko"}}, 145 {"Key":"CAR1", "Record":{"colour":"red","make":"Ford","model":"Mustang","owner":"Brad"}}, 146 {"Key":"CAR2", "Record":{"colour":"green","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}}, 147 {"Key":"CAR3", "Record":{"colour":"yellow","make":"Volkswagen","model":"Passat","owner":"Max"}}, 148 {"Key":"CAR4", "Record":{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}}, 149 {"Key":"CAR5", "Record":{"colour":"purple","make":"Peugeot","model":"205","owner":"Michel"}}, 150 {"Key":"CAR6", "Record":{"colour":"white","make":"Chery","model":"S22L","owner":"Aarav"}}, 151 {"Key":"CAR7", "Record":{"colour":"violet","make":"Fiat","model":"Punto","owner":"Pari"}}, 152 {"Key":"CAR8", "Record":{"colour":"indigo","make":"Tata","model":"Nano","owner":"Valeria"}}, 153 {"Key":"CAR9", "Record":{"colour":"brown","make":"Holden","model":"Barina","owner":"Shotaro"}}] 154 155 These are the 10 cars. A black Tesla Model S owned by Adriana, a red Ford Mustang 156 owned by Brad, a violet Fiat Punto owned by someone named Pari, and so on. The ledger 157 is key/value based and in our implementation the key is ``CAR0`` through ``CAR9``. 158 This will become particularly important in a moment. 159 160 Now let's see what it looks like under the hood (if you'll forgive the pun). 161 Use an editor (e.g. atom or visual studio) and open the ``query.js`` program. 162 163 The inital section of the application defines certain variables such as chaincode ID, channel name 164 and network endpoints: 165 166 .. code:: bash 167 168 var options = { 169 wallet_path : path.join(__dirname, './network/creds'), 170 user_id: 'PeerAdmin', 171 channel_id: 'mychannel', 172 chaincode_id: 'fabcar', 173 network_url: 'grpc://localhost:7051', 174 175 This is the chunk where we construct our query: 176 177 .. code:: bash 178 179 // queryCar - requires 1 argument, ex: args: ['CAR4'], 180 // queryAllCars - requires no arguments , ex: args: [''], 181 const request = { 182 chaincodeId: options.chaincode_id, 183 txId: transaction_id, 184 fcn: 'queryAllCars', 185 args: [''] 186 187 We define the ``chaincode_id`` variable as ``fabcar`` -- allowing us to target this specific chaincode -- and 188 then call the ``queryAllCars`` function defined within that chaincode. 189 190 When we issued the ``node query.js`` command earlier, this specific function was 191 called to query the ledger. However, this isn't the only function that we can pass. 192 193 To take a look at the others, navigate to the ``chaincode`` subdirectory and open 194 ``fabcar.go`` in your editor. You'll see that we have the following functions available 195 to call - ``initLedger``, ``queryCar``, ``queryAllCars``, ``createCar`` and ``changeCarOwner``. 196 Let's take a closer look at the ``queryAllCars`` function to see how it interacts with the 197 ledger. 198 199 .. code:: bash 200 201 func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response { 202 203 startKey := "CAR0" 204 endKey := "CAR999" 205 206 resultsIterator, err := APIstub.GetStateByRange(startKey, endKey) 207 208 The function uses the shim interface function ``GetStateByRange`` to return 209 ledger data between the args of ``startKey`` and ``endKey``. Those keys are 210 defined as ``CAR0`` and ``CAR999`` respectively. Therefore, we could theoretically 211 create 1,000 cars (assuming the keys are tagged properly) and a ``queryAllCars`` would 212 reveal every one. 213 214 Below is a representation of how an app would call different functions in chaincode. 215 216 .. image:: images/RunningtheSample.png 217 218 We can see our ``queryAllCars`` function up there, as well as one called ``createCar`` that 219 will allow us to update the ledger and ultimately append a new block to the chain. 220 But first, let's do another query. 221 222 Go back to the ``query.js`` program and edit the constructor request to query 223 a specific car. We'll do this by changing the function from ``queryAllCars`` 224 to ``queryCar`` and passing a specific "Key" to the args parameter. Let's use 225 ``CAR4`` here. So our edited ``query.js`` program should now contain the 226 following: 227 228 .. code:: bash 229 230 const request = { 231 chaincodeId: options.chaincode_id, 232 txId: transaction_id, 233 fcn: 'queryCar', 234 args: ['CAR4'] 235 236 Save the program and navigate back to your ``fabcar`` directory. Now run the 237 program again: 238 239 .. code:: bash 240 241 node query.js 242 243 You should see the following: 244 245 .. code:: json 246 247 {"colour":"black","make":"Tesla","model":"S","owner":"Adriana"} 248 249 So we've gone from querying all cars to querying just one, Adriana's black Tesla 250 Model S. Using the ``queryCar`` function, we can query against any key (e.g. ``CAR0``) and 251 get whatever make, model, color, and owner correspond to that car. 252 253 Great. Now you should be comfortable with the basic query functions in the chaincode, 254 and the handful of parameters in the query program. Time to update the ledger... 255 256 Updating the Ledger 257 ------------------- 258 259 Now that we’ve done a few ledger queries and added a bit of code, we’re ready to 260 update the ledger. There are a lot of potential updates we could 261 make, but let's just create a new car for starters. 262 263 Ledger updates start with an application generating a transaction proposal. 264 Just like query, a request is constructed to identify the channel ID, 265 function, and specific smart contract to target for the transaction. The program 266 then calls the ``channel.SendTransactionProposal`` API to send the transaction proposal to the peer(s) 267 for endorsement. 268 269 The network (i.e. endorsing peer) returns a proposal response, which the application uses 270 to build and sign a transaction request. This request is sent to the ordering service by 271 calling the ``channel.sendTransaction`` API. The ordering service will bundle the transaction 272 into a block and then "deliver" the block to all peers on a channel for validation. (In our 273 case we have only the single endorsing peer.) 274 275 Finally the application uses the ``eh.setPeerAddr`` API to connect to the peer's 276 event listener port, and calls ``eh.registerTxEvent`` to register events associated 277 with a specific transaction ID. This API allows the application to know the fate of 278 a transaction (i.e. successfully committed or unsuccessful). Think of it as a notification mechanism. 279 280 .. note:: We don't go into depth here on a transaction's lifecycle. Consult the 281 :doc:`txflow` documentation for lower level details on how a transaction 282 is ultimately committed to the ledger. 283 284 The goal with our initial invoke is to simply create a new asset (car in this case). We 285 have a separate javascript program - ``invoke.js`` - that we will use for these transactions. 286 Just like query, use an editor to open the program and navigate to the codeblock where we 287 construct our invocation: 288 289 .. code:: bash 290 291 // createCar - requires 5 args, ex: args: ['CAR11', 'Honda', 'Accord', 'Black', 'Tom'], 292 // changeCarOwner - requires 2 args , ex: args: ['CAR10', 'Barry'], 293 // send proposal to endorser 294 var request = { 295 targets: targets, 296 chaincodeId: options.chaincode_id, 297 fcn: '', 298 args: [''], 299 chainId: options.channel_id, 300 txId: tx_id 301 302 You'll see that we can call one of two functions - ``createCar`` or ``changeCarOwner``. 303 Let's create a red Chevy Volt and give it to an owner named Nick. We're up to ``CAR9`` 304 on our ledger, so we'll use ``CAR10`` as the identifying key here. The updated codeblock 305 should look like this: 306 307 .. code:: bash 308 309 var request = { 310 targets: targets, 311 chaincodeId: options.chaincode_id, 312 fcn: 'createCar', 313 args: ['CAR10', 'Chevy', 'Volt', 'Red', 'Nick'], 314 chainId: options.channel_id, 315 txId: tx_id 316 317 Save it and run the program: 318 319 .. code:: bash 320 321 node invoke.js 322 323 There will be some output in the terminal about Proposal Response and Transaction ID. However, 324 all we're concerned with is this message: 325 326 .. code:: bash 327 328 The transaction has been committed on peer localhost:7053 329 330 The peer emits this event notification, and our application receives it thanks to our 331 ``eh.registerTxEvent`` API. So now if we go back to our ``query.js`` program and call 332 the ``queryCar`` function against an arg of ``CAR10``, we should see the following: 333 334 .. code:: bash 335 336 Response is {"colour":"Red","make":"Chevy","model":"Volt","owner":"Nick"} 337 338 Finally, let's call our last function - ``changeCarOwner``. Nick is feeling generous and 339 he wants to give his Chevy Volt to a man named Barry. So, we simply edit ``invoke.js`` 340 to reflect the following: 341 342 .. code:: bash 343 344 var request = { 345 targets: targets, 346 chaincodeId: options.chaincode_id, 347 fcn: 'changeCarOwner', 348 args: ['CAR10', 'Barry'], 349 chainId: options.channel_id, 350 txId: tx_id 351 352 Execute the program again - ``node invoke.js`` - and then run the query app one final time. 353 We are still querying against ``CAR10``, so we should see: 354 355 .. code:: bash 356 357 Response is {"colour":"Red","make":"Chevy","model":"Volt","owner":"Barry"} 358 359 Additional Resources 360 -------------------- 361 362 The `Hyperledger Fabric Node SDK repo <https://github.com/hyperledger/fabric-sdk-node>`__ 363 is an excellent resource for deeper documentation and sample code. You can also consult 364 the Hyperledger Fabric community and component experts on `Hyperledger Rocket Chat <https://chat.hyperledger.org/home>`__. 365 366 .. Licensed under Creative Commons Attribution 4.0 International License 367 https://creativecommons.org/licenses/by/4.0/