mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-22 17:45:10 +00:00
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:
parent
66b4b2b86a
commit
e31ecf3165
5 changed files with 64 additions and 46 deletions
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
@ -144,9 +145,8 @@ export class AssetTransfer extends Contract {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
record = strValue;
|
record = strValue;
|
||||||
}
|
}
|
||||||
allResults.push({ Key: key, Record: record });
|
allResults.push({Key: key, Record: record});
|
||||||
}
|
}
|
||||||
console.info(allResults);
|
|
||||||
return JSON.stringify(allResults);
|
return JSON.stringify(allResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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];
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"experimentalDecorators": true,
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"target": "es2017",
|
"target": "es2017",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
|
|
|
||||||
|
|
@ -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": []
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue