From 9facb4256bc18adf57fb6e4b0562f15552febf0b Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Thu, 15 Nov 2018 10:47:50 +0000 Subject: [PATCH] [FAB-12851] Add fabcar contract w/ new prog model (JS) Add new FabCar contract sample using the new programming model, written in JavaScript. Add the new contract sample alongside the existing one written in the old programming model, which will be removed in a subsequent change request. Change-Id: Iea46b0a616dbd072b5bd7227ada827a26560f153 Signed-off-by: Simon Stone --- chaincode/fabcar/javascript/.editorconfig | 16 +++ chaincode/fabcar/javascript/.eslintignore | 5 + chaincode/fabcar/javascript/.eslintrc.js | 38 ++++++ chaincode/fabcar/javascript/.gitignore | 77 +++++++++++ chaincode/fabcar/javascript/index.js | 10 ++ chaincode/fabcar/javascript/lib/fabcar.js | 156 ++++++++++++++++++++++ chaincode/fabcar/javascript/package.json | 47 +++++++ 7 files changed, 349 insertions(+) create mode 100755 chaincode/fabcar/javascript/.editorconfig create mode 100644 chaincode/fabcar/javascript/.eslintignore create mode 100644 chaincode/fabcar/javascript/.eslintrc.js create mode 100644 chaincode/fabcar/javascript/.gitignore create mode 100644 chaincode/fabcar/javascript/index.js create mode 100644 chaincode/fabcar/javascript/lib/fabcar.js create mode 100644 chaincode/fabcar/javascript/package.json diff --git a/chaincode/fabcar/javascript/.editorconfig b/chaincode/fabcar/javascript/.editorconfig new file mode 100755 index 00000000..75a13be2 --- /dev/null +++ b/chaincode/fabcar/javascript/.editorconfig @@ -0,0 +1,16 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/chaincode/fabcar/javascript/.eslintignore b/chaincode/fabcar/javascript/.eslintignore new file mode 100644 index 00000000..15958470 --- /dev/null +++ b/chaincode/fabcar/javascript/.eslintignore @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + +coverage diff --git a/chaincode/fabcar/javascript/.eslintrc.js b/chaincode/fabcar/javascript/.eslintrc.js new file mode 100644 index 00000000..6d5751a5 --- /dev/null +++ b/chaincode/fabcar/javascript/.eslintrc.js @@ -0,0 +1,38 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +module.exports = { + env: { + node: true, + mocha: true + }, + parserOptions: { + ecmaVersion: 8, + sourceType: 'script' + }, + extends: "eslint:recommended", + rules: { + indent: ['error', 4], + 'linebreak-style': ['error', 'unix'], + quotes: ['error', 'single'], + semi: ['error', 'always'], + 'no-unused-vars': ['error', { args: 'none' }], + 'no-console': 'off', + curly: 'error', + eqeqeq: 'error', + 'no-throw-literal': 'error', + strict: 'error', + 'no-var': 'error', + 'dot-notation': 'error', + 'no-tabs': 'error', + 'no-trailing-spaces': 'error', + 'no-use-before-define': 'error', + 'no-useless-call': 'error', + 'no-with': 'error', + 'operator-linebreak': 'error', + yoda: 'error', + 'quote-props': ['error', 'as-needed'], + 'no-constant-condition': ["error", { "checkLoops": false }] + } +}; diff --git a/chaincode/fabcar/javascript/.gitignore b/chaincode/fabcar/javascript/.gitignore new file mode 100644 index 00000000..a00ca941 --- /dev/null +++ b/chaincode/fabcar/javascript/.gitignore @@ -0,0 +1,77 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless diff --git a/chaincode/fabcar/javascript/index.js b/chaincode/fabcar/javascript/index.js new file mode 100644 index 00000000..f5911c8c --- /dev/null +++ b/chaincode/fabcar/javascript/index.js @@ -0,0 +1,10 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict'; + +const FabCar = require('./lib/fabcar'); + +module.exports.FabCar = FabCar; +module.exports.contracts = [ FabCar ]; diff --git a/chaincode/fabcar/javascript/lib/fabcar.js b/chaincode/fabcar/javascript/lib/fabcar.js new file mode 100644 index 00000000..53f2faef --- /dev/null +++ b/chaincode/fabcar/javascript/lib/fabcar.js @@ -0,0 +1,156 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict'; + +const { Contract } = require('fabric-contract-api'); + +class FabCar extends Contract { + + async initLedger(ctx) { + console.info('============= START : Initialize Ledger ==========='); + const cars = [ + { + color: 'blue', + make: 'Toyota', + model: 'Prius', + owner: 'Tomoko', + }, + { + color: 'red', + make: 'Ford', + model: 'Mustang', + owner: 'Brad', + }, + { + color: 'green', + make: 'Hyundai', + model: 'Tucson', + owner: 'Jin Soo', + }, + { + color: 'yellow', + make: 'Volkswagen', + model: 'Passat', + owner: 'Max', + }, + { + color: 'black', + make: 'Tesla', + model: 'S', + owner: 'Adriana', + }, + { + color: 'purple', + make: 'Peugeot', + model: '205', + owner: 'Michel', + }, + { + color: 'white', + make: 'Chery', + model: 'S22L', + owner: 'Aarav', + }, + { + color: 'violet', + make: 'Fiat', + model: 'Punto', + owner: 'Pari', + }, + { + color: 'indigo', + make: 'Tata', + model: 'Nano', + owner: 'Valeria', + }, + { + color: 'brown', + make: 'Holden', + model: 'Barina', + owner: 'Shotaro', + }, + ]; + + for (let i = 0; i < cars.length; i++) { + cars[i].docType = 'car'; + await ctx.stub.putState('CAR' + i, Buffer.from(JSON.stringify(cars[i]))); + console.info('Added <--> ', cars[i]); + } + console.info('============= END : Initialize Ledger ==========='); + } + + async queryCar(ctx, carNumber) { + const carAsBytes = await ctx.stub.getState(carNumber); // get the car from chaincode state + if (!carAsBytes || carAsBytes.length === 0) { + throw new Error(`${carNumber} does not exist`); + } + console.log(carAsBytes.toString()); + return carAsBytes.toString(); + } + + async createCar(ctx, carNumber, make, model, color, owner) { + console.info('============= START : Create Car ==========='); + + const car = { + color, + docType: 'car', + make, + model, + owner, + }; + + await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car))); + console.info('============= END : Create Car ==========='); + } + + async queryAllCars(ctx) { + const startKey = 'CAR0'; + const endKey = 'CAR999'; + + const iterator = await ctx.stub.getStateByRange(startKey, endKey); + + const allResults = []; + while (true) { + const res = await iterator.next(); + + if (res.value && res.value.value.toString()) { + console.log(res.value.value.toString('utf8')); + + const Key = res.value.key; + let Record; + try { + Record = JSON.parse(res.value.value.toString('utf8')); + } catch (err) { + console.log(err); + Record = res.value.value.toString('utf8'); + } + allResults.push({ Key, Record }); + } + if (res.done) { + console.log('end of data'); + await iterator.close(); + console.info(allResults); + return JSON.stringify(allResults); + } + } + } + + async changeCarOwner(ctx, carNumber, newOwner) { + console.info('============= START : changeCarOwner ==========='); + + const carAsBytes = await ctx.stub.getState(carNumber); // get the car from chaincode state + if (!carAsBytes || carAsBytes.length === 0) { + throw new Error(`${carNumber} does not exist`); + } + const car = JSON.parse(carAsBytes.toString()); + car.owner = newOwner; + + await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car))); + console.info('============= END : changeCarOwner ==========='); + } + +} + +module.exports = FabCar; diff --git a/chaincode/fabcar/javascript/package.json b/chaincode/fabcar/javascript/package.json new file mode 100644 index 00000000..2f9b98fb --- /dev/null +++ b/chaincode/fabcar/javascript/package.json @@ -0,0 +1,47 @@ +{ + "name": "fabcar", + "version": "1.0.0", + "description": "FabCar contract implemented in JavaScript", + "main": "index.js", + "engines": { + "node": ">=8", + "npm": ">=5" + }, + "scripts": { + "lint": "eslint .", + "pretest": "npm run lint", + "test": "nyc mocha --recursive", + "start": "fabric-chaincode-node start" + }, + "engineStrict": true, + "author": "Hyperledger", + "license": "Apache-2.0", + "dependencies": { + "fabric-contract-api": "1.4.0-beta", + "fabric-shim": "1.4.0-beta" + }, + "devDependencies": { + "chai": "^4.1.2", + "eslint": "^4.19.1", + "mocha": "^5.2.0", + "nyc": "^12.0.2", + "sinon": "^6.0.0", + "sinon-chai": "^3.2.0" + }, + "nyc": { + "exclude": [ + "coverage/**", + "test/**" + ], + "reporter": [ + "text-summary", + "html" + ], + "all": true, + "check-coverage": true, + "statements": 100, + "branches": 100, + "functions": 100, + "lines": 100 + } +}