Decorate Typescript Chaincode

Add the contract-api specific annotations and
enable the experimental features.

Also properly format code according to the linter

Signed-off-by: Brett Logan <brett.t.logan@ibm.com>
This commit is contained in:
Brett Logan 2020-07-24 12:37:10 -04:00 committed by denyeart
parent 66b4b2b86a
commit e31ecf3165
5 changed files with 64 additions and 46 deletions

View file

@ -1,12 +1,26 @@
/* /*
* SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
*/ */
import {Object, Property} from 'fabric-contract-api';
@Object()
export class Asset { export class Asset {
@Property()
public docType?: string; public docType?: string;
@Property()
public ID: string; public ID: string;
@Property()
public Color: string; public Color: string;
@Property()
public Size: number; public Size: number;
@Property()
public Owner: string; public Owner: string;
@Property()
public AppraisedValue: number; public AppraisedValue: number;
} }

View file

@ -2,65 +2,67 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import { Context, Contract } from 'fabric-contract-api'; import {Context, Contract, Returns, Transaction} from 'fabric-contract-api';
import {Asset} from './asset'; import {Asset} from './asset';
export class AssetTransfer extends Contract { export class AssetTransfer extends Contract {
@Transaction()
public async initLedger(ctx: Context) { public async initLedger(ctx: Context) {
const assets: Asset[] = [ const assets: Asset[] = [
{ {
ID: "asset1", ID: 'asset1',
Color: "blue", Color: 'blue',
Size: 5, Size: 5,
Owner: "Tomoko", Owner: 'Tomoko',
AppraisedValue: 300, AppraisedValue: 300,
}, },
{ {
ID: "asset2", ID: 'asset2',
Color: "red", Color: 'red',
Size: 5, Size: 5,
Owner: "Brad", Owner: 'Brad',
AppraisedValue: 400, AppraisedValue: 400,
}, },
{ {
ID: "asset3", ID: 'asset3',
Color: "green", Color: 'green',
Size: 10, Size: 10,
Owner: "Jin Soo", Owner: 'Jin Soo',
AppraisedValue: 500, AppraisedValue: 500,
}, },
{ {
ID: "asset4", ID: 'asset4',
Color: "yellow", Color: 'yellow',
Size: 10, Size: 10,
Owner: "Max", Owner: 'Max',
AppraisedValue: 600, AppraisedValue: 600,
}, },
{ {
ID: "asset5", ID: 'asset5',
Color: "black", Color: 'black',
Size: 15, Size: 15,
Owner: "Adriana", Owner: 'Adriana',
AppraisedValue: 700, AppraisedValue: 700,
}, },
{ {
ID: "asset6", ID: 'asset6',
Color: "white", Color: 'white',
Size: 15, Size: 15,
Owner: "Michel", Owner: 'Michel',
AppraisedValue: 800, AppraisedValue: 800,
}, },
]; ];
for (let i = 0; i < assets.length; i++) { for (const asset of assets) {
assets[i].docType = 'asset'; asset.docType = 'asset';
await ctx.stub.putState(assets[i].ID, Buffer.from(JSON.stringify(assets[i]))); await ctx.stub.putState(asset.ID, Buffer.from(JSON.stringify(asset)));
console.info('Added <--> ', assets[i]); console.info(`Asset ${asset.ID} initialized`);
} }
} }
// createAsset issues a new asset to the world state with given details. // createAsset issues a new asset to the world state with given details.
@Transaction()
public async createAsset(ctx: Context, id: string, color: string, size: number, owner: string, appraisedValue: number) { public async createAsset(ctx: Context, id: string, color: string, size: number, owner: string, appraisedValue: number) {
const asset = { const asset = {
ID: id, ID: id,
@ -69,73 +71,72 @@ export class AssetTransfer extends Contract {
Owner: owner, Owner: owner,
AppraisedValue: appraisedValue, AppraisedValue: appraisedValue,
}; };
await ctx.stub.putState(id, Buffer.from(JSON.stringify(asset))); await ctx.stub.putState(id, Buffer.from(JSON.stringify(asset)));
} }
// readAsset returns the asset stored in the world state with given id. // readAsset returns the asset stored in the world state with given id.
@Transaction(false)
public async readAsset(ctx: Context, id: string): Promise<string> { public async readAsset(ctx: Context, id: string): Promise<string> {
const assetJSON = await ctx.stub.getState(id); // get the asset from chaincode state const assetJSON = await ctx.stub.getState(id); // get the asset from chaincode state
if (!assetJSON || assetJSON.length === 0) { if (!assetJSON || assetJSON.length === 0) {
throw new Error(`The asset ${id} does not exist`); throw new Error(`The asset ${id} does not exist`);
} }
return assetJSON.toString(); return assetJSON.toString();
} }
// updateAsset updates an existing asset in the world state with provided parameters. // updateAsset updates an existing asset in the world state with provided parameters.
@Transaction()
public async updateAsset(ctx: Context, id: string, color: string, size: number, owner: string, appraisedValue: number) { public async updateAsset(ctx: Context, id: string, color: string, size: number, owner: string, appraisedValue: number) {
const exists = await this.assetExists(ctx, id); const exists = await this.assetExists(ctx, id);
if (!exists) { if (!exists) {
throw new Error(`The asset ${id} does not exist`); throw new Error(`The asset ${id} does not exist`);
} }
// overwritting original asset with new asset // overwriting original asset with new asset
let updatedAsset = { const updatedAsset = {
ID: id, ID: id,
Color: color, Color: color,
Size: size, Size: size,
Owner: owner, Owner: owner,
AppraisedValue: appraisedValue, AppraisedValue: appraisedValue,
}; };
return ctx.stub.putState(id, Buffer.from(JSON.stringify(updatedAsset))); return ctx.stub.putState(id, Buffer.from(JSON.stringify(updatedAsset)));
} }
// deleteAsset deletes an given asset from the world state. // deleteAsset deletes an given asset from the world state.
@Transaction()
public async deleteAsset(ctx: Context, id: string) { public async deleteAsset(ctx: Context, id: string) {
const exists = await this.assetExists(ctx, id); const exists = await this.assetExists(ctx, id);
if (!exists) { if (!exists) {
throw new Error(`The asset ${id} does not exist`); throw new Error(`The asset ${id} does not exist`);
} }
return ctx.stub.deleteState(id); return ctx.stub.deleteState(id);
} }
// assetExists returns true when asset with given ID exists in world state. // assetExists returns true when asset with given ID exists in world state.
@Transaction(false)
@Returns('boolean')
public async assetExists(ctx: Context, id: string): Promise<boolean> { public async assetExists(ctx: Context, id: string): Promise<boolean> {
const assetJSON = await ctx.stub.getState(id); const assetJSON = await ctx.stub.getState(id);
if (!assetJSON || assetJSON.length === 0) { return assetJSON && assetJSON.length > 0;
return false;
}
return true;
} }
// transferAsset updates the owner field of asset with given id in the world state. // transferAsset updates the owner field of asset with given id in the world state.
@Transaction()
public async transferAsset(ctx: Context, id: string, newOwner: string) { public async transferAsset(ctx: Context, id: string, newOwner: string) {
let assetString = await this.readAsset(ctx, id); const assetString = await this.readAsset(ctx, id);
const asset = JSON.parse(assetString);
let asset = JSON.parse(assetString);
asset.Owner = newOwner; asset.Owner = newOwner;
await ctx.stub.putState(id, Buffer.from(JSON.stringify(asset))); await ctx.stub.putState(id, Buffer.from(JSON.stringify(asset)));
} }
// getAllAssets returns all assets found in the world state. // getAllAssets returns all assets found in the world state.
@Transaction(false)
@Returns('string')
public async getAllAssets(ctx: Context): Promise<string> { public async getAllAssets(ctx: Context): Promise<string> {
const allResults = []; const allResults = [];
// range query with empty string for startKey and endKey does an open-ended query of all assets in the chaincode namespace. // 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("", "")) { for await (const {key, value} of ctx.stub.getStateByRange('', '')) {
const strValue = Buffer.from(value).toString('utf8'); const strValue = Buffer.from(value).toString('utf8');
let record; let record;
try { try {
@ -146,7 +147,6 @@ export class AssetTransfer extends Contract {
} }
allResults.push({Key: key, Record: record}); allResults.push({Key: key, Record: record});
} }
console.info(allResults);
return JSON.stringify(allResults); return JSON.stringify(allResults);
} }

View file

@ -3,6 +3,7 @@
*/ */
import {AssetTransfer} from './assetTransfer'; import {AssetTransfer} from './assetTransfer';
export {AssetTransfer} from './assetTransfer'; export {AssetTransfer} from './assetTransfer';
export const contracts: any[] = [AssetTransfer]; export const contracts: any[] = [AssetTransfer];

View file

@ -1,5 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"experimentalDecorators": true,
"outDir": "dist", "outDir": "dist",
"target": "es2017", "target": "es2017",
"moduleResolution": "node", "moduleResolution": "node",

View file

@ -15,7 +15,9 @@
"no-string-throw": true, "no-string-throw": true,
"no-var-keyword": true, "no-var-keyword": true,
"no-trailing-whitespace": true, "no-trailing-whitespace": true,
"object-literal-key-quotes": [true, "as-needed"] "object-literal-key-quotes": [true, "as-needed"],
"object-literal-sort-keys": false,
"max-line-length": false
}, },
"rulesDirectory": [] "rulesDirectory": []
} }