[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 <sstone1@uk.ibm.com>
This commit is contained in:
Simon Stone 2018-11-15 10:47:50 +00:00
parent 1c8211371b
commit 9facb4256b
7 changed files with 349 additions and 0 deletions

View file

@ -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

View file

@ -0,0 +1,5 @@
#
# SPDX-License-Identifier: Apache-2.0
#
coverage

View file

@ -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 }]
}
};

77
chaincode/fabcar/javascript/.gitignore vendored Normal file
View file

@ -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

View file

@ -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 ];

View file

@ -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;

View file

@ -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
}
}