mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 15:35:09 +00:00
new file: LandContract/application-typescript/src/Admin.js new file: LandContract/application-typescript/src/app.ts new file: LandContract/application-typescript/src/registerEnrollUser.js new file: LandContract/application-typescript/src/utils/AppUtil.ts new file: LandContract/application-typescript/src/utils/CAUtil.ts new file: LandContract/application-typescript/tsconfig.json new file: LandContract/application-typescript/tslint.json new file: chaincode-typescript/Dockerfile new file: chaincode-typescript/dist/Contract/landAsset.d.ts new file: chaincode-typescript/dist/Contract/landAsset.js new file: chaincode-typescript/dist/Contract/landAsset.js.map new file: chaincode-typescript/dist/Contract/landTransaction.d.ts new file: chaincode-typescript/dist/Contract/landTransaction.js new file: chaincode-typescript/dist/Contract/landTransaction.js.map new file: chaincode-typescript/dist/asset.d.ts new file: chaincode-typescript/dist/asset.js new file: chaincode-typescript/dist/asset.js.map new file: chaincode-typescript/dist/assetTransfer.d.ts new file: chaincode-typescript/dist/assetTransfer.js new file: chaincode-typescript/dist/assetTransfer.js.map new file: chaincode-typescript/dist/index.d.ts new file: chaincode-typescript/dist/index.js new file: chaincode-typescript/dist/index.js.map new file: chaincode-typescript/docker/docker-entrypoint.sh new file: chaincode-typescript/npm-shrinkwrap.json new file: chaincode-typescript/package.json new file: chaincode-typescript/src/Contract/Admin.js new file: chaincode-typescript/src/Contract/landAsset.ts new file: chaincode-typescript/src/Contract/landTransaction.ts new file: chaincode-typescript/src/Contract/registerEnrollUser.js new file: chaincode-typescript/src/Contract/userRequest.ts new file: chaincode-typescript/src/Contract/wallet/admin.id new file: chaincode-typescript/src/Contract/wallet/user123.id new file: chaincode-typescript/src/asset.ts new file: chaincode-typescript/src/assetTransfer.ts new file: chaincode-typescript/src/index.ts new file: chaincode-typescript/tsconfig.json new file: chaincode-typescript/tslint.json modified: test-network/compose/compose-ca.yaml modified: test-network/compose/compose-test-net.yaml modified: test-network/compose/docker/docker-compose-bft-test-net.yaml modified: test-network/compose/docker/docker-compose-test-net.yaml modified: test-network/configtx/configtx.yaml modified: test-network/network.sh modified: test-network/organizations/ccp-generate.sh modified: test-network/organizations/cryptogen/crypto-config-org2.yaml new file: test-network/organizations/cryptogen/crypto-config-org3.yaml new file: test-network/organizations/cryptogen/crypto-config-org4.yaml modified: test-network/organizations/fabric-ca/registerEnroll.sh new file: test-network_org4.zip
173 lines
6.4 KiB
TypeScript
173 lines
6.4 KiB
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';
|
|
|
|
@Info({title: 'AssetTransfer', description: 'Smart contract for trading assets'})
|
|
export class AssetTransferContract extends Contract {
|
|
|
|
@Transaction()
|
|
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.
|
|
@Transaction()
|
|
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.
|
|
@Transaction(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.
|
|
@Transaction()
|
|
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.
|
|
@Transaction()
|
|
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.
|
|
@Transaction(false)
|
|
@Returns('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.
|
|
@Transaction()
|
|
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.
|
|
@Transaction(false)
|
|
@Returns('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);
|
|
}
|
|
|
|
}
|