@siglesiasg/node-red-hyperledger-fabric-gateway
Version:
Hyperledger Fabric 2.x nodes for node-red with latest fabric-gateway library
174 lines (160 loc) • 6.55 kB
text/typescript
/*
* SPDX-License-Identifier: Apache-2.0
*/
// Deterministic JSON.stringify()
import {Context, Contract, Info, Returns, Transaction} from 'fabric-contract-api';
import stringify from 'json-stringify-deterministic';
import sortKeysRecursive from 'sort-keys-recursive';
import {Asset} from './asset';
({title: 'AssetTransfer', description: 'Smart contract for trading assets'})
export class AssetTransferContract extends Contract {
()
public async InitLedger(ctx: Context): Promise<void> {
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 (const asset of assets) {
asset.docType = 'asset';
// example of how to write to world state deterministically
// use convetion of alphabetic order
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
// when retrieving data, in any lang, the order of data will be the same and consequently also the corresonding hash
await ctx.stub.putState(asset.ID, Buffer.from(stringify(sortKeysRecursive(asset))));
console.info(`Asset ${asset.ID} initialized`);
}
}
// 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): Promise<void> {
const exists = await this.AssetExists(ctx, id);
if (exists) {
throw new Error(`The asset ${id} already exists`);
}
const asset = {
ID: id,
Color: color,
Size: size,
Owner: owner,
AppraisedValue: appraisedValue,
};
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
await ctx.stub.putState(id, Buffer.from(stringify(sortKeysRecursive(asset))));
}
// ReadAsset returns the asset stored in the world state with given id.
(false)
public async ReadAsset(ctx: Context, id: string): Promise<string> {
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): Promise<void> {
const exists = await this.AssetExists(ctx, id);
if (!exists) {
throw new Error(`The asset ${id} does not exist`);
}
// overwriting original asset with new asset
const updatedAsset = {
ID: id,
Color: color,
Size: size,
Owner: owner,
AppraisedValue: appraisedValue,
};
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
return ctx.stub.putState(id, Buffer.from(stringify(sortKeysRecursive(updatedAsset))));
}
// DeleteAsset deletes an given asset from the world state.
()
public async DeleteAsset(ctx: Context, id: string): Promise<void> {
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.
(false)
('boolean')
public async AssetExists(ctx: Context, id: string): Promise<boolean> {
const assetJSON = await ctx.stub.getState(id);
return assetJSON && assetJSON.length > 0;
}
// TransferAsset updates the owner field of asset with given id in the world state, and returns the old owner.
()
public async TransferAsset(ctx: Context, id: string, newOwner: string): Promise<string> {
const assetString = await this.ReadAsset(ctx, id);
const asset = JSON.parse(assetString);
const oldOwner = asset.Owner;
asset.Owner = newOwner;
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
await ctx.stub.putState(id, Buffer.from(stringify(sortKeysRecursive(asset))));
return oldOwner;
}
// GetAllAssets returns all assets found in the world state.
(false)
('string')
public async GetAllAssets(ctx: Context): Promise<string> {
const allResults = [];
// range query with empty string for startKey and endKey does an open-ended query of all assets in the chaincode namespace.
const iterator = await ctx.stub.getStateByRange('', '');
let result = await iterator.next();
while (!result.done) {
const strValue = Buffer.from(result.value.value.toString()).toString('utf8');
let record;
try {
record = JSON.parse(strValue);
} catch (err) {
console.log(err);
record = strValue;
}
allResults.push(record);
result = await iterator.next();
}
return JSON.stringify(allResults);
}
}