From a42bbba2c58b8353d71bf6774a79aefc2d7e7593 Mon Sep 17 00:00:00 2001 From: Chongxin Luo Date: Tue, 16 Jun 2020 15:42:13 -0400 Subject: [PATCH] Adding chaincode-typescript to asset-transfer-basic sample. Signed-off-by: Chongxin Luo --- .../chaincode-typescript/.gitignore | 16 ++ .../chaincode-typescript/package.json | 62 +++++++ .../chaincode-typescript/src/asset.ts | 12 ++ .../chaincode-typescript/src/assetTransfer.ts | 153 ++++++++++++++++++ .../chaincode-typescript/src/index.ts | 8 + .../chaincode-typescript/tsconfig.json | 16 ++ .../chaincode-typescript/tslint.json | 21 +++ 7 files changed, 288 insertions(+) create mode 100644 asset-transfer-basic/chaincode-typescript/.gitignore create mode 100644 asset-transfer-basic/chaincode-typescript/package.json create mode 100644 asset-transfer-basic/chaincode-typescript/src/asset.ts create mode 100644 asset-transfer-basic/chaincode-typescript/src/assetTransfer.ts create mode 100644 asset-transfer-basic/chaincode-typescript/src/index.ts create mode 100644 asset-transfer-basic/chaincode-typescript/tsconfig.json create mode 100644 asset-transfer-basic/chaincode-typescript/tslint.json diff --git a/asset-transfer-basic/chaincode-typescript/.gitignore b/asset-transfer-basic/chaincode-typescript/.gitignore new file mode 100644 index 00000000..79bfe1a3 --- /dev/null +++ b/asset-transfer-basic/chaincode-typescript/.gitignore @@ -0,0 +1,16 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + + +# Coverage directory used by tools like istanbul +coverage + +# Dependency directories +node_modules/ +jspm_packages/ +package-lock.json + +# Compiled TypeScript files +dist + diff --git a/asset-transfer-basic/chaincode-typescript/package.json b/asset-transfer-basic/chaincode-typescript/package.json new file mode 100644 index 00000000..2b681fc1 --- /dev/null +++ b/asset-transfer-basic/chaincode-typescript/package.json @@ -0,0 +1,62 @@ +{ + "name": "asset-transfer-basic", + "version": "1.0.0", + "description": "Asset Transfer Basic contract implemented in TypeScript", + "main": "dist/index.js", + "typings": "dist/index.d.ts", + "engines": { + "node": ">=12", + "npm": ">=5" + }, + "scripts": { + "lint": "tslint -c tslint.json 'src/**/*.ts'", + "pretest": "npm run lint", + "test": "nyc mocha -r ts-node/register src/**/*.spec.ts", + "start": "fabric-chaincode-node start", + "build": "tsc", + "build:watch": "tsc -w", + "prepublishOnly": "npm run build" + }, + "engineStrict": true, + "author": "Hyperledger", + "license": "Apache-2.0", + "dependencies": { + "fabric-contract-api": "^2.0.0", + "fabric-shim": "^2.0.0" + }, + "devDependencies": { + "@types/chai": "^4.1.7", + "@types/mocha": "^5.2.5", + "@types/node": "^10.12.10", + "@types/sinon": "^5.0.7", + "@types/sinon-chai": "^3.2.1", + "chai": "^4.2.0", + "mocha": "^5.2.0", + "nyc": "^14.1.1", + "sinon": "^7.1.1", + "sinon-chai": "^3.3.0", + "ts-node": "^7.0.1", + "tslint": "^5.11.0", + "typescript": "^3.1.6" + }, + "nyc": { + "extension": [ + ".ts", + ".tsx" + ], + "exclude": [ + "coverage/**", + "dist/**" + ], + "reporter": [ + "text-summary", + "html" + ], + "all": true, + "check-coverage": true, + "statements": 100, + "branches": 100, + "functions": 100, + "lines": 100 + } +} diff --git a/asset-transfer-basic/chaincode-typescript/src/asset.ts b/asset-transfer-basic/chaincode-typescript/src/asset.ts new file mode 100644 index 00000000..56d33439 --- /dev/null +++ b/asset-transfer-basic/chaincode-typescript/src/asset.ts @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +export class Asset { + public docType?: string; + public ID: string; + public Color: string; + public Size: number; + public Owner: string; + public AppraisedValue: number; +} diff --git a/asset-transfer-basic/chaincode-typescript/src/assetTransfer.ts b/asset-transfer-basic/chaincode-typescript/src/assetTransfer.ts new file mode 100644 index 00000000..04ebcb99 --- /dev/null +++ b/asset-transfer-basic/chaincode-typescript/src/assetTransfer.ts @@ -0,0 +1,153 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Context, Contract } from 'fabric-contract-api'; +import { Asset } from './asset'; + +export class AssetTransfer extends Contract { + + public async initLedger(ctx: Context) { + const assets: Asset[] = [ + { + ID: "asset1", + Color: "blue", + Size: 5, + Owner: "Tomoko", + AppraisedValue: 300, + }, + { + ID: "asset2", + Color: "red", + Size: 5, + Owner: "Brad", + AppraisedValue: 400, + }, + { + ID: "asset3", + Color: "green", + Size: 10, + Owner: "Jin Soo", + AppraisedValue: 500, + }, + { + ID: "asset4", + Color: "yellow", + Size: 10, + Owner: "Max", + AppraisedValue: 600, + }, + { + ID: "asset5", + Color: "black", + Size: 15, + Owner: "Adriana", + AppraisedValue: 700, + }, + { + ID: "asset6", + Color: "white", + Size: 15, + Owner: "Michel", + AppraisedValue: 800, + }, + ]; + + for (let i = 0; i < assets.length; i++) { + assets[i].docType = 'asset'; + await ctx.stub.putState(assets[i].ID, Buffer.from(JSON.stringify(assets[i]))); + console.info('Added <--> ', assets[i]); + } + } + + // createAsset issues a new asset to the world state with given details. + public async createAsset(ctx: Context, id: string, color: string, size: number, owner: string, appraisedValue: number) { + const asset = { + ID: id, + Color: color, + Size: size, + Owner: owner, + AppraisedValue: appraisedValue, + }; + + await ctx.stub.putState(id, Buffer.from(JSON.stringify(asset))); + } + + // readAsset returns the asset stored in the world state with given id. + public async readAsset(ctx: Context, id: string): Promise { + const assetJSON = await ctx.stub.getState(id); // get the asset from chaincode state + if (!assetJSON || assetJSON.length === 0) { + throw new Error(`The asset ${id} does not exist`); + } + + return assetJSON.toString(); + } + + // updateAsset updates an existing asset in the world state with provided parameters. + public async updateAsset(ctx: Context, id: string, color: string, size: number, owner: string, appraisedValue: number) { + const exists = await this.assetExists(ctx, id); + if (!exists) { + throw new Error(`The asset ${id} does not exist`); + } + + // overwritting original asset with new asset + let updatedAsset = { + ID: id, + Color: color, + Size: size, + Owner: owner, + AppraisedValue: appraisedValue, + }; + + return ctx.stub.putState(id, Buffer.from(JSON.stringify(updatedAsset))); + } + + // deleteAsset deletes an given asset from the world state. + public async deleteAsset(ctx: Context, id: string) { + const exists = await this.assetExists(ctx, id); + if (!exists) { + throw new Error(`The asset ${id} does not exist`); + } + + return ctx.stub.deleteState(id); + } + + // assetExists returns true when asset with given ID exists in world state. + public async assetExists(ctx: Context, id: string): Promise { + const assetJSON = await ctx.stub.getState(id); + if (!assetJSON || assetJSON.length === 0) { + return false; + } + return true; + } + + // transferAsset updates the owner field of asset with given id in the world state. + public async transferAsset(ctx: Context, id: string, newOwner: string) { + let assetString = await this.readAsset(ctx, id); + + let asset = JSON.parse(assetString); + asset.Owner = newOwner; + + await ctx.stub.putState(id, Buffer.from(JSON.stringify(asset))); + } + + // getAllAssets returns all assets found in the world state. + public async getAllAssets(ctx: Context): Promise { + const allResults = []; + // range query with empty string for startKey and endKey does an open-ended query of all assets in the chaincode namespace. + for await (const { key, value } of ctx.stub.getStateByRange("", "")) { + const strValue = Buffer.from(value).toString('utf8'); + let record; + try { + record = JSON.parse(strValue); + } catch (err) { + console.log(err); + record = strValue; + } + allResults.push({ Key: key, Record: record }); + } + console.info(allResults); + return JSON.stringify(allResults); + } + +} diff --git a/asset-transfer-basic/chaincode-typescript/src/index.ts b/asset-transfer-basic/chaincode-typescript/src/index.ts new file mode 100644 index 00000000..a5f5e17b --- /dev/null +++ b/asset-transfer-basic/chaincode-typescript/src/index.ts @@ -0,0 +1,8 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +import { AssetTransfer } from './assetTransfer'; +export { AssetTransfer } from './assetTransfer'; + +export const contracts: any[] = [AssetTransfer]; diff --git a/asset-transfer-basic/chaincode-typescript/tsconfig.json b/asset-transfer-basic/chaincode-typescript/tsconfig.json new file mode 100644 index 00000000..8c96ea07 --- /dev/null +++ b/asset-transfer-basic/chaincode-typescript/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "outDir": "dist", + "target": "es2017", + "moduleResolution": "node", + "module": "commonjs", + "declaration": true, + "sourceMap": true + }, + "include": [ + "./src/**/*" + ], + "exclude": [ + "./src/**/*.spec.ts" + ] +} diff --git a/asset-transfer-basic/chaincode-typescript/tslint.json b/asset-transfer-basic/chaincode-typescript/tslint.json new file mode 100644 index 00000000..33ccbf3c --- /dev/null +++ b/asset-transfer-basic/chaincode-typescript/tslint.json @@ -0,0 +1,21 @@ +{ + "defaultSeverity": "error", + "extends": [ + "tslint:recommended" + ], + "jsRules": {}, + "rules": { + "indent": [true, "spaces", 4], + "linebreak-style": [true, "LF"], + "quotemark": [true, "single"], + "semicolon": [true, "always"], + "no-console": false, + "curly": true, + "triple-equals": true, + "no-string-throw": true, + "no-var-keyword": true, + "no-trailing-whitespace": true, + "object-literal-key-quotes": [true, "as-needed"] + }, + "rulesDirectory": [] +}